最大子序和:暴力->递归->动规->线段树
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
LeetCode:53. 最大子序和
题解
显而易见的暴力解法
最容易想到的便是暴力穷举所有的子段和的开头,显而易见时间复杂度是O(n^2)。
代码:
class Solution {
public int maxSubArray(int[] nums) {
int maxSum = Integer.MIN_VALUE;
int n = nums.length;
for(int i = 0;i < n;i++){//穷举所有的开头
int thisSum = 0;
for(int j = i;j < n;j++){//穷举当前开头的子段和
thisSum += nums[j];
maxSum = Math.max(maxSum,thisSum);
}
}
return maxSum;
}
}
不是那么难的分治解法
本题也是分治解法应用的一个典型例子。“分”即将数组分为前后两段求解,“治”即分别求两段的最大子段和,“合”即比较两段的最大子段和和跨段的子段和,取最大值。
代码:
class Solution {
public int maxSubArray(int[] nums) {
return maxSub(nums, 0, nums.length - 1);
}
private int maxSub(int nums[], int left, int right){
if (left == right){
return nums[left];
}
int maxSum = 0;
int middle = (left + right) / 2;
int leftMaxSum = maxSub(nums, left, middle);//最半段最大子段和
int rightMaxSum = maxSub(nums, middle + 1, right);//右半段最大子段和
int leftRightSum = Integer.MIN_VALUE;//左半段以middle结尾的最大子段和
int rightLeftSum = Integer.MIN_VALUE;//右半段以middle+1开头的最大子段和
int thisLeftRightSum = 0;
int thisRightLeftSum = 0;
for(int j = middle;j >= left;j--){
thisLeftRightSum += nums[j];
leftRightSum = Math.max(leftRightSum,thisLeftRightSum);
}
for(int j = middle+1;j <= right;j++){
thisRightLeftSum += nums[j];
rightLeftSum = Math.max(rightLeftSum,thisRightLeftSum);
}
int crossMaxSum = leftRightSum + rightLeftSum;//跨段最大子段和
if(crossMaxSum>leftMaxSum&&crossMaxSum>rightMaxSum){
return crossMaxSum;
}else{
return Math.max(leftMaxSum,rightMaxSum);
}
}
}
时间复杂度分析:合的时间复杂度是O(n),分的时间复杂度是2*T(n/2)。
则\(T(n) = 2T(\frac{n}{2}) + O(n)\)。根据主定理, θ(f(n)) = θ(n) ,\(\log_b a = \log_2 2 = 1\),两者渐进复杂度相当,故时间复杂度为θ(nlogn)。
巧妙的动态规划
暴力解法穷举所有的开头,那么我们可不可以穷举所有的结尾?
对于数组中的任意一个元素,他要么是某个子段和的结尾,要么自己单独成为子段。因此后面的状态可以由前面的状态得出,可以使用动态规划。
代码:
class Solution {
public int maxSubArray(int[] nums) {
int maxSum = Integer.MIN_VALUE;
int thisSum = 0;
for(int i=0;i<nums.length;i++){
//如果已经求得的子段和加上当前元素比当前元素还小,说明前面求得的子段和没有意义
//那么子段和应更新为当前元素
thisSum = Math.max(nums[i],thisSum+nums[i]);
maxSum = Math.max(maxSum,thisSum);
}
return maxSum;
}
}
时间复杂度分析:只遍历一遍数组,时间复杂度为O(n),辅助空间为常数空间O(1)。
更加复杂的递归,线段树的隐用
最大子序和:暴力->递归->动规->线段树的更多相关文章
- 【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids
给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q. 我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q ...
- ZKW线段树 非递归版本的线段树
学习和参考 下面是支持区间修改和区间查询的zkw线段树模板,先记下来. #include <algorithm> #include <iterator> #include &l ...
- NOIP2013 提高组day2 2 花匠 动规 找拐点 树状数组
花匠 描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体 ...
- hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)
题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...
- CF620E New Year Tree 线段树+dfs序+bitset
线段树维护 dfs 序是显然的. 暴力建 60 个线段树太慢,于是用 bitset 优化就好了 ~ code: #include <bits/stdc++.h> #define M 63 ...
- cdoj 574 High-level ancients dfs序+线段树
High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...
- bzoj2819 DFS序 + LCA + 线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=2819 题意:树上单点修改及区间异或和查询. 思维难度不高,但是题比较硬核. 整体思路是维护每一个结 ...
- Codeforces343D(SummerTrainingDay06-F dfs序+线段树)
D. Water Tree time limit per test:4 seconds memory limit per test:256 megabytes input:standard input ...
- hdu5692【dfs序】【线段树】
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
随机推荐
- Docker Swarm(一)集群部署
一.机器环境 机器规划 172.16.0.89 swarm的manager节点 manager-node 172.16.0.90 swarm的node节点 node1 机器版本(均是:CentOS L ...
- Jira&Confluence服务器安装
1.Mysql安装 参考https://confluence.atlassian.com/doc/database-setup-for-mysql-128747.html 创建相应的数据库 CREAT ...
- Mysql_源码包安装详细过程
一.mysql安装 1.二进制安装 2.源码包安装 3.rpm包安装 1.源码包安装 1)上传或下载源码包 [root@db02 ~]# rz mysql-5.6.46.tar.gz 2)安装依赖 由 ...
- 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)
1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间 认为桢收完,总线空闲中断是在检测到在接收数据后, ...
- MyBatis 模糊查询的 4 种实现方式
引言 MyBatis 有 4 种方式可以实现模糊查询. 员工信息表 ( tb_employee ) 如下: id name sex email birthday address 001 张一凡 男 z ...
- 如何使用 IoC
创建Maven工程,pom.xml添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project x ...
- Java List去重以及效率分析
List去重无非几种方法: 下面文章提供的两种: https://blog.csdn.net/u012156163/article/details/78338574, 以及使用List.stream. ...
- (续篇)Selenium 安装配置以及如何解决('chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/ch)或者(unknown error:cannot find Chrome binary)问题?
注:本帖针对小小白哦~~(づ ̄3 ̄)づ╭- 接pip安装的帖子,不需要的直接跳过... 首先上图,出现如下的错误,那你可是找到知己了: 或者: 抱歉抱歉,这图截的不太清晰,凑合着用吧,但是也能看出来错 ...
- TensorRT 加速性能分析
TensorRT 加速性能分析 Out-of-the-box GPU Performance 模型推理性能是什么意思?在为用户评估潜在的候选项时,不测量数据库查询和预筛选(例如决策树或手动逻辑)的贡献 ...
- 【NX二次开发】获取当前鼠标选择的对象 UF_UI_ask_global_sel_object_list
先选择多个对象object,然后使用此函数获取选择的对象的tag,最后就可以使用object的一些函数了. ufun例子: extern DllExport void ufusr(char *parm ...