题目描述

给定一个整数数组 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)。

更加复杂的递归,线段树的隐用

最大子序和:暴力->递归->动规->线段树的更多相关文章

  1. 【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids

    给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q. 我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q ...

  2. ZKW线段树 非递归版本的线段树

    学习和参考 下面是支持区间修改和区间查询的zkw线段树模板,先记下来. #include <algorithm> #include <iterator> #include &l ...

  3. NOIP2013 提高组day2 2 花匠 动规 找拐点 树状数组

    花匠 描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体 ...

  4. hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)

    题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...

  5. CF620E New Year Tree 线段树+dfs序+bitset

    线段树维护 dfs 序是显然的. 暴力建 60 个线段树太慢,于是用 bitset 优化就好了 ~ code: #include <bits/stdc++.h> #define M 63 ...

  6. cdoj 574 High-level ancients dfs序+线段树

    High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...

  7. bzoj2819 DFS序 + LCA + 线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=2819 题意:树上单点修改及区间异或和查询. 思维难度不高,但是题比较硬核. 整体思路是维护每一个结 ...

  8. Codeforces343D(SummerTrainingDay06-F dfs序+线段树)

    D. Water Tree time limit per test:4 seconds memory limit per test:256 megabytes input:standard input ...

  9. hdu5692【dfs序】【线段树】

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

随机推荐

  1. Docker Swarm(一)集群部署

    一.机器环境 机器规划 172.16.0.89 swarm的manager节点 manager-node 172.16.0.90 swarm的node节点 node1 机器版本(均是:CentOS L ...

  2. Jira&Confluence服务器安装

    1.Mysql安装 参考https://confluence.atlassian.com/doc/database-setup-for-mysql-128747.html 创建相应的数据库 CREAT ...

  3. Mysql_源码包安装详细过程

    一.mysql安装 1.二进制安装 2.源码包安装 3.rpm包安装 1.源码包安装 1)上传或下载源码包 [root@db02 ~]# rz mysql-5.6.46.tar.gz 2)安装依赖 由 ...

  4. 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)

    1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间  认为桢收完,总线空闲中断是在检测到在接收数据后, ...

  5. MyBatis 模糊查询的 4 种实现方式

    引言 MyBatis 有 4 种方式可以实现模糊查询. 员工信息表 ( tb_employee ) 如下: id name sex email birthday address 001 张一凡 男 z ...

  6. 如何使用 IoC

    创建Maven工程,pom.xml添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project x ...

  7. Java List去重以及效率分析

    List去重无非几种方法: 下面文章提供的两种: https://blog.csdn.net/u012156163/article/details/78338574, 以及使用List.stream. ...

  8. (续篇)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安装的帖子,不需要的直接跳过... 首先上图,出现如下的错误,那你可是找到知己了: 或者: 抱歉抱歉,这图截的不太清晰,凑合着用吧,但是也能看出来错 ...

  9. TensorRT 加速性能分析

    TensorRT 加速性能分析 Out-of-the-box GPU Performance 模型推理性能是什么意思?在为用户评估潜在的候选项时,不测量数据库查询和预筛选(例如决策树或手动逻辑)的贡献 ...

  10. 【NX二次开发】获取当前鼠标选择的对象 UF_UI_ask_global_sel_object_list

    先选择多个对象object,然后使用此函数获取选择的对象的tag,最后就可以使用object的一些函数了. ufun例子: extern DllExport void ufusr(char *parm ...