题目描述

给定一个整数数组 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. Spring Cloud(Dalston.SR1)

    Spring Cloud 示例项目地址:https://github.com/Yanshaoshuai/microservicecloud Eureka 集群搭建 microservicecloud- ...

  2. ceph总结复习

    一.ceph概念 Ceph是一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统.ceph 的统一体现在可以提供文件系统.块存储和对象存储,分布式体现在可以动态扩展. 什么是块存储/对象存 ...

  3. STM32SD卡 (U盘)IAP升级

    http://www.openedv.com/posts/list/65104.htm

  4. NLP文本分类

    引言 其实最近挺纠结的,有一点点焦虑,因为自己一直都期望往自然语言处理的方向发展,梦想成为一名NLP算法工程师,也正是我喜欢的事,而不是为了生存而工作.我觉得这也是我这辈子为数不多的剩下的可以自己去追 ...

  5. 安卓开发(2)—— Kotlin语言概述

    安卓开发(2)-- Kotlin语言概述 Android的官方文档都优先采用Kotlin语言了,学它来进行Android开发已经是一种大势所趋了. 这里只讲解部分的语法. 如何运行Kotlin代码 这 ...

  6. HDFS 05 - HDFS 的元数据管理(FSImage、EditLog、Checkpoint)

    目录 1 - NameNode 的启动流程 2 - NameNode 的元数据 2.1 EditLog 操作日志 2.2 查看 EditLog 文件 2.3 FSImage 元数据镜像 2.4 查看 ...

  7. Linux将一个文件夹或文件夹下的所有内容复制到另一个文件夹

    Linux将一个文件夹或文件夹下的所有内容复制到另一个文件夹     1.将一个文件夹下的所有内容复制到另一个文件夹下 cp -r /home/packageA/* /home/cp/packageB ...

  8. 如何查看Oracle SID即instance_name 和 dbname区别

    SID 和  instance_name是一个实例名字db_name 是数据库名字搞清两个概念,数据库和实例 实例:实例是数据库启动时初始化的一组进程和内存结构 数据库:数据库则指的是用户存储数据的一 ...

  9. NVIDIA GPU卷积网络的自动调谐

    NVIDIA GPU卷积网络的自动调谐 针对特定设备和工作负载的自动调整对于获得最佳性能至关重要.这是关于如何为NVIDIA GPU调整整个卷积网络. NVIDIA GPU在TVM中的操作实现是以模板 ...

  10. 激光雷达Lidar Architecture and Lidar Design(下)

    Considerations on Lidar Design 双基地还是单基地? 双轴还是同轴? 几何重叠 向上还是向下看? 关心分散还是只关心时间? 发射器和接收器的波长 是否可调? 发射器和接收器 ...