剑指 Offer 42. 连续子数组的最大和
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
双指针解法:
1 class Solution { 2 public int maxSubArray(int[] nums) { 3 if(nums.length==0) return 0; 4 if(nums.length==1) return nums[0]; 5 int i=0,j,len=nums.length,sum,max=Integer.MIN_VALUE; 6 while(i<len){ 7 sum=0; 8 j=i; 9 while(sum>=0&&j<len){ 10 sum+=nums[j++]; 11 max=sum>max?sum:max; 12 } 13 i++; 14 } 15 return max; 16 } 17 }
递归版解法:
1 class Solution { 2 public int helper(int[] nums,int start,int end){ 3 if(start==end) return nums[start]; 4 int mid=(start+end)/2; 5 int leftSum=helper(nums,start,mid); 6 int rightSum=helper(nums,mid+1,end); 7 int crossSum=Crosshelper(nums,start,mid,end); 8 return Math.max(Math.max(leftSum,rightSum),crossSum); 9 } 10 public int Crosshelper(int[] nums,int start,int mid,int end){ 11 if(start==end) return nums[start]; 12 int sum=0; 13 int t=Integer.MIN_VALUE; 14 for(int i=mid;i>=start;i--){ 15 sum+=nums[i]; 16 t=Math.max(sum,t); 17 } 18 sum=0; 19 int t1=Integer.MIN_VALUE; 20 for(int i=mid+1;i<=end;i++){ 21 sum+=nums[i]; 22 t1=Math.max(sum,t1); 23 } 24 return t+t1; 25 } 26 public int maxSubArray(int[] nums) { 27 if(nums.length==0) return 0; 28 return helper(nums,0,nums.length-1); 29 } 30 }
动态规划解法:
1 class Solution { 2 public int maxSubArray(int[] nums) { 3 if(nums.length==0) return 0; 4 int res = nums[0]; 5 for(int i = 1; i < nums.length; i++) { 6 nums[i] += Math.max(nums[i - 1], 0); 7 res = Math.max(res, nums[i]); 8 } 9 return res; 10 } 11 }
复杂度分析:
时间复杂度 O(N)O(N) : 线性遍历数组 numsnums 即可获得结果,使用 O(N)O(N) 时间。
空间复杂度 O(1)O(1) : 使用常数大小的额外空间。