题目描述

给定一个整数数组 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. 源码安装Python3

    源码安装Python3 一.安装Python3需要的依赖包 [root@localhost ~]# yum install -y gcc make wget openssl openssl-devel ...

  2. IT菜鸟之虚拟机VMware的使用

    虚拟机安装完成了,以下是虚拟机的使用. 双击快捷方式,打开vmware虚拟机. 点击创建新虚拟机,这里可以选择创建方式,可以点击典型并一路下一步创建,我们这里讲自定义创建. 这里选择兼容版本,大家可以 ...

  3. 6.3-4 zip、unzip

    zip:打包和压缩文件     zip压缩格式是Windows与Linux等多平台通用的压缩格式.和gzip命令相比,zip命令压缩文件不仅不会删除源文件,而且还可以压缩目录.   zip命令的参数选 ...

  4. python文件处理(对比和筛选)版本2

    场景:对比两个txt文件的差异,将对比结果写入html,将不同部分写入另一个txt #!/user/bin/python #!coding=utf-8 # -*- coding: utf-8 -*- ...

  5. Python对比两个txt文件内容

    difflib模块作为python的标准库模块,无需安装,作用是比对文本之间的差异,且支持输出可读性比较强的html格式.#!coding=utf-8 # 2018-9-19 import sys i ...

  6. Spring5.0源码学习系列之事务管理概述

    Spring5.0源码学习系列之事务管理概述(十一),在学习事务管理的源码之前,需要对事务的基本理论比较熟悉,所以本章节会对事务管理的基本理论进行描述 1.什么是事务? 事务就是一组原子性的SQL操作 ...

  7. jackjson学习2+CVE-2019-14379漏洞分析

    最近想着分析jackson,jackson和fastjson有点相似,浅蓝大神的文章很好,个人受益匪浅 昨天简单说了下jackson的用法,现在继续拓扑,补充前置知识,前置知识补充的足够多,那么漏洞分 ...

  8. 解决mysql无法远程连接的问题

    前言 最近开发中遇到一个问题,mysql在服务器本地可以登录,但是远程通过3306端口却不可以.这个问题困扰了我一周之久,终于在今天解决了.在解决的过程中试了很多的方法,遂记录下来,希望能给大家一些提 ...

  9. VirtualBox安装配置CentOS7(含网络连接配置)

    最近需要用到CentOS7,特地在虚拟机上安装一遍,中间走了很多弯路,特地在此处进行记录 前置条件: 1.本地完成Oracle VM VirtualBox,我安装的是6.1版本 2.下载CentOS安 ...

  10. Vue的常用特性

    Vue的常用特性 一.表单基本操作 都是通过v-model 单选框 1. 两个单选框需要同时通过v-model 双向绑定 一个值 2. 每一个单选框必须要有value属性 且value值不能一样 3. ...