题目描述

给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。

例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],

连续子序列 [4,-1,2,1] 的和最大,为 6。

扩展练习:

若你已实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

思路

思路一:

maxSum 必然是以nums[i](取值范围为nums[0] ~ nums[n-1])结尾的某段构成的,也就是说maxSum的candidate必然是以nums[i]结果的。如果遍历每个candidate,然后进行比较,那么就能找到最大的maxSum了。

假设把nums[i]之前的连续段叫做sum。可以很容易想到:

  1. 如果sum>=0,就可以和nums[i]拼接在一起构成新的sum。因为不管nums[i]多大,加上一个正数总会更大,这样形成一个新的candidate。
  2. 反之,如果sum<0,就没必要和nums[i]拼接在一起了。因为不管nums[i]多小,加上一个负数总会更小。此时由于题目要求数组连续,所以没法保留原sum,所以只能让sum等于从nums[i]开始的新的一段数了,这一段数字形成新的candidate。
  3. 如果每次得到新的candidate都和全局的maxSum进行比较,那么必然能找到最大的max sum subarray.

在循环过程中,用maxSum记录历史最大的值。从nums[0]到nums[n-1]一步一步地进行。

思路二:

遍历array,对于每一个数字,我们判断,(之前的sum + 这个数字) 和 (这个数字) 比大小,如果(这个数字)自己就比 (之前的sum + 这个数字) 大的话,那么说明不需要再继续加了,直接从这个数字,开始继续,因为它自己已经比之前的sum都大了。

反过来,如果 (之前的sum + 这个数字)大于 (这个数字)就继续加下去。

利用动态规划做题。

只遍历数组一遍,当从头到尾部遍历数组A, 遇到一个数有两种选择 (1)加入之前subArray (2)自己另起一个subArray

设状态S[i], 表示以A[i]结尾的最大连续子序列和,状态转移方程如下:

S[i] = max(S[i-1] + A[i],A[i])

从状态转移方程上S[i]只与S[i-1]有关,与其他都无关,因此可以用一个变量来记住前一个的最大连续数组和就可以了。这样就可以节省空间了。

代码实现

package Array;

/**
* 53.Maximum Subarray(最大子序和)
* 给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。
* 例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],
* 连续子序列 [4,-1,2,1] 的和最大,为 6。
*/
public class Solution53 {
public static void main(String[] args) {
Solution53 solution53 = new Solution53();
int[] arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
System.out.println(solution53.maxSubArray(arr));
} /**
* maxSum 必然是以nums[i](取值范围为nums[0] ~ nums[n-1])结尾的某段构成的,也就是说maxSum的candidate必然是以nums[i]结果的。如果遍历每个candidate,然后进行比较,那么就能找到最大的maxSum了。
* 假设把nums[i]之前的连续段叫做sum。可以很容易想到:
* 1. 如果sum>=0,就可以和nums[i]拼接在一起构成新的sum。因为不管nums[i]多大,加上一个正数总会更大,这样形成一个新的candidate。
* 2. 反之,如果sum<0,就没必要和nums[i]拼接在一起了。因为不管nums[i]多小,加上一个负数总会更小。此时由于题目要求数组连续,所以没法保留原sum,所以只能让sum等于从nums[i]开始的新的一段数了,这一段数字形成新的candidate。
* 3. 如果每次得到新的candidate都和全局的maxSum进行比较,那么必然能找到最大的max sum subarray.
* 在循环过程中,用maxSum记录历史最大的值。从nums[0]到nums[n-1]一步一步地进行。
*
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
int sum = 0; //或者初始化为 sum = INT_MIN 也OK。
int maxSum = nums[0];
for (int i = 0; i < nums.length; i++) {
if (sum >= 0) {
sum += nums[i];
} else {
sum = nums[i];
}
if (sum > maxSum) {
maxSum = sum;
}
}
return maxSum;
} /**
* 遍历array,对于每一个数字,我们判断,(之前的sum + 这个数字) 和 (这个数字) 比大小,如果(这个数字)自己就比 (之前的sum + 这个数字) 大的话,那么说明不需要再继续加了,直接从这个数字,开始继续,因为它自己已经比之前的sum都大了。
* 反过来,如果 (之前的sum + 这个数字)大于 (这个数字)就继续加下去。
* 利用动态规划做题。
* 只遍历数组一遍,当从头到尾部遍历数组A, 遇到一个数有两种选择 (1)加入之前subArray (2)自己另起一个subArray
* 设状态S[i], 表示以A[i]结尾的最大连续子序列和,状态转移方程如下:
* S[i] = max(S[i-1] + A[i],A[i])
* 从状态转移方程上S[i]只与S[i-1]有关,与其他都无关,因此可以用一个变量来记住前一个的最大连续数组和就可以了。
* 这样就可以节省空间了。
* 时间复杂度:O(n) 空间复杂度:O(1)
*/
public int maxSubArray_2(int[] nums) {
int sum = 0; //或者初始化为 sum = INT_MIN 也OK。
int maxSum = nums[0];
//动态规划
for (int i = 0; i < nums.length; i++) {
sum = Math.max(sum + nums[i], nums[i]);
maxSum = Math.max(sum, maxSum);
}
return maxSum;
}
}

Leetcode#53.Maximum Subarray(最大子序和)的更多相关文章

  1. LeetCode 53. Maximum Subarray最大子序和 (C++)

    题目: Given an integer array nums, find the contiguous subarray (containing at least one number) which ...

  2. 【LeetCode】53. Maximum Subarray 最大子序和 解题报告(Python & C++ & Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力解法 动态规划 日期 题目地址: https:/ ...

  3. [LeetCode] 53. Maximum Subarray 最大子数组

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  4. [leetcode]53. Maximum Subarray最大子数组和

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  5. 53. Maximum Subarray最大子序和

    网址:https://leetcode.com/problems/maximum-subarray/submissions/ 很简单的动态规划 我们可以把 dp[i] 表示为index为 i 的位置上 ...

  6. 【LeetCode】Maximum Subarray(最大子序和)

    这道题是LeetCode里的第53道题. 题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1 ...

  7. [LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  8. [array] leetcode - 53. Maximum Subarray - Easy

    leetcode - 53. Maximum Subarray - Easy descrition Find the contiguous subarray within an array (cont ...

  9. 小旭讲解 LeetCode 53. Maximum Subarray 动态规划 分治策略

    原题 Given an integer array nums, find the contiguous subarray (containing at least one number) which ...

随机推荐

  1. 美丽的webpack-bundle-analyzer

    webpack-bundle-analyzer -- Webpack 插件和 CLI 实用程序,她可以将打包后的内容束展示为方便交互的直观树状图,让我们知道我们所构建包中真正引入的内容: 我们可以借助 ...

  2. NCBI通过氨基酸位置查看相邻SNP

    进入NCBI网站 在SNP的搜索框中输入SNP位点,比如“rs52811957” 在弹出的对话框中选择“Gene View” 进入以后会显示该变异相邻SNP.原始氨基酸.变异后的氨基酸.positio ...

  3. PHP实现异步处理

    resource fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, ...

  4. js解析base64

    var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ...

  5. 二进制部署 Kubernetes 集群

    二进制部署 Kubernetes 集群   提供的几种Kubernetes部署方式 minikube Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,尝试Kubernet ...

  6. 25 个常用的 Linux iptables 规则

    # 1. 删除所有现有规则 iptables -F   # 2. 设置默认的 chain 策略 iptables -P INPUT DROP iptables -P FORWARD DROP ipta ...

  7. qml: QtCharts模块的使用(基本配置)------<一>

    QtCharts模块可以用于绘制图表: 导入模块: import QtCharts 2.2 例子: import QtQuick 2.0 import QtCharts 2.2 ChartView { ...

  8. 入侵检测中需要监控的注册表路径研究(Windows Registry Security Check)

    1. Windows注册表简介 注册表(Registry,繁体中文版Windows称之为登录档)是Microsoft Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息.早在Wind ...

  9. JMeter:Dashboard Report自动生成测试报告的巧用和避坑

    官网地址查阅:http://jmeter.apache.org/usermanual/generating-dashboard.html 最近在压测过程中使用 Generating Report Da ...

  10. HDU 1019(求最小公倍数 **)

    题意是求一组数的最小公倍数,不用存,每次输入即刻处理即可. 补充一点:两个自然数的最大公约数与它们的最小公倍数的乘积等于这两个数的乘积. 代码如下: #include <bits/stdc++. ...