LeetCode Maximum Subarray 通俗讲解解法的背后原理

来源:互联网 发布:级联删除sql语句 编辑:程序博客网 时间:2024/06/07 00:11

题目:

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.

找到题目的解法不难,第一种解法的出处
第二种解法的出处

但是理解其背后的原理却是比较困难的,我在代码的后面贴上了我对于解法原理的通俗演义,建议在看之前先看看第二种解法的出处

public static int maxSubArray1(int[] nums) {        int sum = 0;        int max = nums[0];        for (int i = 0; i < nums.length; i++) {            sum += nums[i];            if (sum > max)                max = sum;            if (sum < 0)                sum = 0;        }        return max;    }
public int maxSubArray2(int[] A) {        if(A==null || A.length==0)            return 0;        int global = A[0];        int local = A[0];        for(int i=1;i<A.length;i++)        {            local = Math.max(A[i],local+A[i]);            global = Math.max(local,global);        }        return global;    }

背后原理:

当我们遍历到第i个数,对于前面的i-1个数必定会有一个连续的子集Q和最大,那么当到了第i个数时,最有可能挑战Q地位的肯定是包含第i个数的一个连续子集,因为若是在第i个数之前,连续子集的最大和是Q,那么从第一个数到第i-1个数这个集合中所有的可能的连续子集的和都被Q折服,被Q打败了,现在到了第i个数,出现了一个变量,如此一来,若有可能出现一个比Q更大的,那么这个连续的子集,必定是包含第i个数的一个子集。
对于第i个数来说,它要组建子集的队伍要打败Q,它就要审视在它之前的数对于它的队伍来说有没有增益,也就是说它们的和是否大于0,如果有增益的话就让队伍包括它们,否则就舍弃它们。
然后,就和Q决一死战。
但是对于我们的算法来说,为了降低时间复杂性,不能到了第i个数再去审视之前的数对于队伍的增益,而是要在到i之前就去审视。
这就是第一种解法中

if (sum < 0)                sum = 0;

的作用,sum是为第i个数准备的预备队,当发现这个预备队会对队伍有损害,即小于0时,就要坚决地舍弃,从头开始为第i个数组件队伍。
也是第二种解法

  local = Math.max(A[i],local+A[i]);

的作用,看看是单独第i个数的力量大,还是加上前面的队伍力量大。

1 0
原创粉丝点击