#53 Maximum Subarray最大子串和
2015-05-25 15:55
281 查看
题目:
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array
the contiguous subarray
题解:
比较经典的一个问题,是学习的好材料。
解1:穷举,O(n²)复杂度,意料中的超时。
解2:&&Kadane算法
这是我的解法。和Kadane算法 相似有没有,很激动有没有!由于相似,所以放在一起说明了。
首先有这样的结论,对于nums[1,...,n],如果nums[i,...,j]是满足和最大的子串,那么对于任意的i=<k<=j,有nums[i,...,k]的和大于0。利用一个数组sum[i]记录局部子串和。遍历数组,对于i,若sun[i-1]>0,则将nums[i]加入之前子串,并记录子串和sum[i]=sun[i-1]+nums[i],否则nums[i]单开子串,记录子串和sum[i]=nums[i]。最后维护一个全局最大值max,即使返回的最大子串和。
Kadane算法 :
原理:将数组从左到右分割为若干子串,使得除了最后一个子串之外,其余子串的各元素之和小于0,且对于所有子串nums[i...j]和任意k(i<=k<j),有nums[i...k]的和大于0。满足条件的和最大子串,只能是上述某个子串的前缀,而不可能跨越多个子串。
原理详细可参考:http://blog.csdn.net/joylnwang/article/details/6859677
执行流程:从头到尾遍历目标数组,将数组分割为满足上述条件的子串,同时得到各子串的最大前缀和,然后比较各子串的最大前缀和,得到最终答案。
以array={-2, 1, -3, 4, -1, 2, 1, -5, 4}为例,通过遍历,可以将数组分割为如下3个子串(-2),(1,-3),(4,-1,2,1,-5,4),这里对于(-2)这样的情况,单独分为一组。各子串的最大前缀和为-2,1,6,所以目标串的最大子串和为6。
解3:分治法:
最大子串和的区间有以下三种情况(low,high分别为左右边界,mid为(low+high)/2):(1)
区间完全在 A[low,mid-1];(2) 区间完全在 A[mid+1,high];(3)
区间包含有 A[mid],等价于从中间元素开始往左累加的最大值
+ 从中间元素开始往右累加的最大值
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array
[−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray
[4,−1,2,1]has the largest sum =
6.
题解:
比较经典的一个问题,是学习的好材料。
解1:穷举,O(n²)复杂度,意料中的超时。
public class Solution { public int maxSubArray(int[] nums) { int subsum; int maxsum=nums[0];//注意这里不是int maxsum=<strong>0</strong>; int len=nums.length; for(int i=0;i<len;i++){ subsum=0; for(int j=i;j<len;j++) subsum+=nums[i]; maxsum=Math.max(subsum,maxsum); } return maxsum; } }
解2:&&Kadane算法
这是我的解法。和Kadane算法 相似有没有,很激动有没有!由于相似,所以放在一起说明了。
首先有这样的结论,对于nums[1,...,n],如果nums[i,...,j]是满足和最大的子串,那么对于任意的i=<k<=j,有nums[i,...,k]的和大于0。利用一个数组sum[i]记录局部子串和。遍历数组,对于i,若sun[i-1]>0,则将nums[i]加入之前子串,并记录子串和sum[i]=sun[i-1]+nums[i],否则nums[i]单开子串,记录子串和sum[i]=nums[i]。最后维护一个全局最大值max,即使返回的最大子串和。
public class Solution { public int maxSubArray(int[] nums) { int[] sum = new int[nums.length]; int maxsub = nums[0]; sum[0] = nums[0]; for(int i = 1; i < nums.length; i++){ sum[i] = Math.max(nums[i], sum[i - 1] + nums[i]); maxsub = Math.max(maxsub, sum[i]); } return maxsub; } }
Kadane算法 :
原理:将数组从左到右分割为若干子串,使得除了最后一个子串之外,其余子串的各元素之和小于0,且对于所有子串nums[i...j]和任意k(i<=k<j),有nums[i...k]的和大于0。满足条件的和最大子串,只能是上述某个子串的前缀,而不可能跨越多个子串。
原理详细可参考:http://blog.csdn.net/joylnwang/article/details/6859677
执行流程:从头到尾遍历目标数组,将数组分割为满足上述条件的子串,同时得到各子串的最大前缀和,然后比较各子串的最大前缀和,得到最终答案。
以array={-2, 1, -3, 4, -1, 2, 1, -5, 4}为例,通过遍历,可以将数组分割为如下3个子串(-2),(1,-3),(4,-1,2,1,-5,4),这里对于(-2)这样的情况,单独分为一组。各子串的最大前缀和为-2,1,6,所以目标串的最大子串和为6。
public class Solution { public int maxSubArray(int[] nums) { int max_ending_here = 0; int max_so_far = nums[0]; for(int i = 0; i < nums.length; i++){ if(max_ending_here < 0) max_ending_here = 0; max_ending_here += nums[i]; max_so_far = Math.max(max_so_far, max_ending_here); } return max_so_far; } }
解3:分治法:
最大子串和的区间有以下三种情况(low,high分别为左右边界,mid为(low+high)/2):(1)
区间完全在 A[low,mid-1];(2) 区间完全在 A[mid+1,high];(3)
区间包含有 A[mid],等价于从中间元素开始往左累加的最大值
+ 从中间元素开始往右累加的最大值
public class Solution { public int maxSubArray(int[] nums) { return divide(nums, 0, nums.length-1); } public int divide(int nums[], int low, int high){ if(low == high) return nums[low]; if(low == high-1) return Math.max(nums[low]+nums[high], Math.max(nums[low], nums[high])); int mid = (low+high)/2; int lmax = divide(nums, low, mid-1); int rmax = divide(nums, mid+1, high); int mmax = nums[mid]; int tmp = mmax; for(int i = mid-1; i >=low; i--){ tmp += nums[i]; if(tmp > mmax) mmax = tmp; } tmp = mmax; for(int i = mid+1; i <= high; i++){ tmp += nums[i]; if(tmp > mmax) mmax = tmp; } return Math.max(mmax, Math.max(lmax, rmax)); } }
相关文章推荐
- LeetCode-53-Maximum Subarray(最大和子串)
- Scala Maximum Subarray 最大子串 leetcode 53
- Leetcode 53 Maximum Subarray 最大子串和
- LeetCode 53 分治算法,求最大子串
- 【DP入门】最大连续子串和
- leetcode-java.T003_LongestSubstringWithoutRepeatingCharacters 给定一个字符串,找字符中的最大非重复子串
- 给定一个字符串s,找出s中最长的回文子串,你可以假设s的最大长度是1000。
- 算法复习之:最大子串和问题
- Java 获取两个字符串的最大子串
- 用动态规划算法对最大子串问题的java实现
- 和最大连续子串续——和最大连续子矩阵
- c++之求一个字符串中的最大回文子串
- 最大连续子串问题
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)
- java语言编程:求两个字符串的最大子串
- NYOJ 44 & 104 - 最大连续子串和(矩阵最大子矩阵和)
- C - 求整数数组中和最大子串
- 最大连续子序列和,乘积,最长递增子串,最长公共子串,子序列等问题(动态规划等)
- 最大乘积子串-----输出子串和乘积
- 动态规划解最大和子串