LeetCode---53. Maximum Subarray

53. Maximum Subarray

题目

https://leetcode.com/problems/maximum-subarray/description/
给出一个整数数组,要求找到最大和子串(至少包含一个数字),返回最大和。
LeetCode---53. Maximum Subarray_第1张图片

思路及解法

这里我们须要注意子串和子序列之间的差别。
子串是指数组中连续的若干个元素。而子序列仅仅要求各元素的顺序与其在数组中一致,而没有连续的要求。对于一个元素数为n的数组,其含有 2 n 2^{n} 2n
个子序列和 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1)个子串。

另外,我们还需要知道一个结论。对于array[1…n],假设array[i…j]就是满足和最大的子串,那么对于不论什么k(i<=k<=j),我们有array[i…k]的和大于0。因为假设存在k使得array[i…k]的和小于0。那么我们就有array[k+1…j]的和大于array[i…j],这与我们假设的array[i…j]就是array中和最大子串矛盾。
简单说,如果是最大和子串,那么在这个子串的范围内,某个元素前面的子子串一定大于零

另外,在学习别人的方法的时候,看到一个博主说道面试时闻到了这道题,所以也贴过来,增长点经验~~

这道题在Amazon电面二的时候问到过,不过不是返回最大值,而是返回subarray。
这样的话我们要保存local和global的starting index以及length。 
Follow up是overflow或者underflow该怎么处理, throw ArithmeticException就可以了。
方法一

首先我们遍历每一个元素,做两个判断,第一,当前元素是不是要和其他元素组成一个子串,也就是这个元素是不是要放到当前的子串里。第二,如果当前子串不是最大子串了,我们怎么更新一个子串。
假设我们现在站在某一个元素k的位置上,他的前面已经有一个子串了,这时候如果这个子串的和是小于零的,根据我们上面给出的结论,这个子串一定不是最大子串,所以我们应该更新子串。那么有一个问题是新的子串的起始位置在哪里呢?其实,我们知道这个子串是我们一步一步迭代来的,也就是这个子串的每一个子串都是经过这个方法得来的,所以他们都满足上面说的结论。如果这个起始位置在这个子串的内部,比如位置x,那么x前面的子子串是大于零的,而本身这个子串小于零,所以x后面的子子串也一定小于零,那么将x作为起始位置相当于给新的子串增加了一个小于零的子子串,根据结论,这个新的子串一定不是最大和子串。所以,新的起始位置一定不在子串的内部,应该在位置k。
如果这个子串是大于零的,根据结论,我们是可以吧k放到这个子串里的,但是我们并不能保证加入k后子串的和变大,因为k可能小于零,但同时s后面的元素加入子串后有可能使得子串和变大。所以我们就把符合结论的子串的和通过一个result变量记录下来,在每一次更新子串后,看看新的子串和是不是比result大了,如果是,就更新result,否则result保持不变。最终,我们输出result就行了。
但是这种方法的效率低,只有11%

方法二

看了discussion里高票回答,思路和方法的一样,都是动态规划,只是他用的数组来表示的,更容易理解,所以也贴一个代码过来。

方法一
class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int k = nums[0];
        
        for(int i=1; iresult){
                result = k;
            }
            //result = Math.max(k, result);  最后一个判断换为这个语句可以提升到27%
        }
        return result;
    }
}
class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        //int k = nums[0];  //其实dp数组是可以替换为k的,这样可以减少空间复杂度
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        
        for(int i=1; i 0 ? dp[i - 1] : 0);
            result = Math.max(dp[i], result);
        }
        return result;
    }
}

你可能感兴趣的:(LeetCode---53. Maximum Subarray)