子数组,这个题一开始肯定想到用滑动窗口,但它的数组有负数,所以不知道往哪移动,只能用动态规划。
用f(i)表示以i结尾的最大和数组,则要找的就是max{f(i)},为什么不用f(i)表示0到i的最大和,因为没法用f(i-1)推出f(i),f(i-1)不一定包括num[i-1]。所以f(i)=max(num[i],num[i]+f(i-1));
因为它是连续的,所以一个for就够了,子序列一般是O(n2)
所以遍历的时候如果cur小于0,就舍弃cur并令它等于当前的arr[i]。大于0的话就cur加上当前数。最后如果cur大于max,就令max=cur
class Solution {
public int maxSubArray(int[] nums) {
if(nums==null || nums.length==0)return 0;
int res=nums[0];
int[] dp=new int[nums.length];
dp[0]=nums[0];
for(int i=1;i<nums.length;i++){
dp[i]=Math.max(nums[i]+dp[i-1],nums[i]);
res=Math.max(res,dp[i]);
}
return res;
}
}
如果加上一个条件是我可以跳过一次的话。
则再加一个数组f[i]来表示以i结尾且到目前为止没有用这次机会的最大和,
dp[i]表示以i结尾使用过这次机会最大值,两者取一个最大值即可。
f[i]=max(d[i-1]+num[i],num[i])
dp[i]=max(dp[i-1]+nums[i],d[i-1]);
class Solution {
public int maximumSum(int[] arr) {
int[] f=new int[arr.length];
int[] dp=new int[arr.length];
int res=arr[0];
f[0]=arr[0];
dp[0]=-100000;
for(int i=1;i<arr.length;i++){
f[i]=Math.max(f[i-1]+arr[i],arr[i]);
dp[i]=Math.max(dp[i-1]+arr[i],f[i-1]);
res=Math.max(res,f[i]);
res=Math.max(res,dp[i]);
}
return res;
}
}