给定一个长度为 n 的数组 arr ,返回其中任意连续子数组的最大累加和
题目保证没有全为负数的数据
数据范围:,数组中元素值
要求:时间复杂度为,空间复杂度为
public int maxsumofSubarray (int[] arr) { int maxSum = 0; int sum = 0; for(int i = 0; i < arr.length; i++){ sum = sum + arr[i] > 0 ? sum + arr[i] : 0; maxSum = maxSum > sum ? maxSum : sum; } return maxSum; }
//第一种:累加和小于0,则归零继续往后面遍历 public int maxsumofSubarray (int[] arr) { if(arr==null||arr.length==0) return -1; int n=arr.length,max=0,sum=0; for(int i=0;i<n;i++){ sum=sum+arr[i]; if(sum>max) max=sum; if(sum<0) sum=0; } return max; } } //第二种,dp 存储到第i个元素时的最大和 public int maxsumofSubarray (int[] arr) { int n=arr.length,dp=0,max=0; for(int i=0;i<n;i++){ dp=Math.max(arr[i],dp+arr[i]); max=Math.max(max,dp); } return max; }
public int maxsumofSubarray (int[] arr) { //1.dp状态设置: dp[i]就是以nums[i]为结尾的的连续子数组的最大和 int[] dp = new int[arr.length]; //2.初态设置:dp[0]必须包含nums[0] 所以: dp[0] = arr[0]; int res = dp[0]; //3.转移方程: //因为nums[i]无论如何都要包括 那么可以选择的余地就是dp[i-1]了 //dp[i-1]<0 那么不如只选nums[i]了 dp[i-1]>0 那就nums[i]带上dp[i-1] for (int i = 1; i < arr.length; i++) { dp[i] = dp[i-1]>0?dp[i-1]+arr[i]:arr[i]; //由于无论如何都要包括nums[i] 那么如果最后的nums[len-1]<0 //那么此时dp[len-1]肯定不是最大连续和 需要max筛选 res = Math.max(res,dp[i]); } return res; }
js榜都是错的,怎么通过的都?
设置一个变量max存储全局最大值,一个变量cur存储当前的和;
然后开始遍历数组:
function maxsumofSubarray( arr ) { let max = 0, cur = 0; for (const num of arr) { cur += num; if (cur < 0) cur = 0; else if (max < cur) max = cur; } return max; }
function maxsumofSubarray( arr ) { // write code here let max = Number.MIN_VALUE let pre = 0 for(let i = 0; i < arr.length; i++) { pre = Math.max(arr[i], pre + arr[i]) max = Math.max(max, pre) } return max } module.exports = { maxsumofSubarray : maxsumofSubarray };
public class Solution { public int maxsumofSubarray (int[] arr) { int max = 0; int cumsum = 0; for(int i = 0; i < arr.length; i++){ if(cumsum >= 0){ cumsum += arr[i]; } else{ cumsum = arr[i]; } max = Math.max(max, cumsum); } return max; } }
# # max sum of the subarray # @param arr int整型一维数组 the array # @return int整型 class Solution: def maxsumofSubarray(self , arr ): # write code here num_c = 0 num_r = arr[0] for i in range(len(arr)): num_c += arr[i] if i > 0: num_r = max(arr[i],num_c,num_r) if num_c < 0: num_c = 0 return num_r
int maxsumofSubarray(vector<int>& arr) { int temp = 0; int result = arr[0]; for(int i=0;i<arr.size();i++) { temp = max(temp+arr[i],arr[i]); result = max(result,temp); } return result; // write code here } 遍历数组,看看是累加到当前元素的和大 还是当前元素大,并更新temp的值
# # max sum of the subarray # @param arr int整型一维数组 the array # @return int整型 # class Solution: def maxsumofSubarray(self , arr ): # write code here total = 0 maxi = arr[0] for i in range(len(arr)): total = total + arr[i] if total <= 0: total = 0 elif total >= maxi: maxi = total return maxi
有写go的小伙伴吗? 思路: .子数组必然以正数开始,其实就是分析一个子结构,类似:[+a1, +a2, -a3, -a4, +a5] .问题本质就是,在两个正子数组之间的负子数组是否应该被计算在内的问题 .如果负子数组元素和的绝对值分别小于前后正子数组的元素和,则应该被计算在内,否则前后正子数组的元素和的较大者为可能的结果。 package main func maxsumofSubarray( arr []int ) int { res := 0 tmp := 0 for i := 0; i < len(arr); i++ { res += arr[i] if arr[i] > 0 && res <= 0 { res = arr[i] } if arr[i] < 0 && res > tmp{ tmp = res } } return res }
class Solution { public: /** * max sum of the subarray * @param arr int整型vector the array * @return int整型 */ int maxsumofSubarray(vector<int>& arr) { int a = arr.size(); int dp[a]; dp[0] = arr[0]; for(int i = 1; i < arr.size(); i++){ if(dp[i-1] >=0){ dp[i] = dp[i-1]+arr[i]; } else{ dp[i] = arr[i]; } } return dp[a-1]; } };
class Solution { public: /** * max sum of the subarray * @param arr int整型vector the array * @return int整型 */ int maxsumofSubarray(vector<int>& arr) { int a = arr.size(); int dp[a]; dp[0] = arr[0]; int _max = dp[0]; for(int i = 1; i < arr.size(); i++){ if(dp[i-1] >=0){ dp[i] = dp[i-1]+arr[i]; } else{ dp[i] = arr[i]; } _max = max(_max, dp[i]); } return _max; } };
import java.util.*; public class Solution { /** * 【逆向思维】要找出一个子串,使得和最大 * 相对来说是去掉了左边和右边的数据,剩下一个子串 * 所以用左右两个指针,依次找从左到右,从右到左的连续最小和index * 那么这两者之间的子串就是目标子串 * 同时,需要考虑指针碰撞,也就是所有值为负数,那么找出其中的最大的单值 */ public int maxsumofSubarray (int[] arr) { if(arr.length <=1){ return arr[0]; } int leftMin = arr[0]; int leftIndex = 0; int tmp = arr[0]; // 保存最大值,用于指针碰撞后返回 int max=arr[0]; for(int i = 1; i < arr.length; i ++){ tmp += arr[i]; if(tmp < leftMin){ leftMin = tmp; leftIndex = i; } if(arr[i]>max){ max = arr[i]; } } int rightMin = arr[arr.length-1]; int rightIndex = arr.length-1; tmp = arr[arr.length-1]; for(int j = arr.length-2; j >= 0; j --){ tmp += arr[j]; if(tmp < rightMin){ rightMin = tmp; rightIndex = j; } } // 指针碰撞了,返回最大值 if(leftIndex>=rightIndex){ return max; }else{ // 找到左右指针,同时要判断左右指针的值是否大于0 tmp = 0; for(int k = leftIndex+1; k <= rightIndex-1; k ++){ tmp += arr[k]; } if(arr[leftIndex]>0){ tmp += arr[leftIndex]; } if(arr[rightIndex]>0){ tmp += arr[rightIndex]; } return tmp; } } }
动态规划
public class Solution { /** * max sum of the subarray * @param arr int整型一维数组 the array * @return int整型 */ //动态规划 时间O(n),空间O(1) //转移方程 /*dp[i] 代表以元素 nums[i] 为结尾的连续子数组最大和 当dp[i-1] >0 时:执行 dp[i] = dp[i-1] + nums[i] 当dp[i-1] <=0 时:执行 dp[i] = nums[i]; */ public int maxsumofSubarray (int[] arr){ // write code here if (arr.length == 0) return 0; int len = arr.length; int cur,pre = arr[0],res = arr[0]; for(int i = 1;i < len;++i){ cur = arr[i]; cur = cur + Math.max(pre,0); pre = cur; res = Math.max(res,cur); //也可以直接在arr[] 上做修改 // arr[i] = arr[i] + Math.max(arr[i-1],0); // res = Math.max(arr[i],res); } return res; } }