算法-leetcode-每日一题-求最大子数组

分析:该题是一道经典的题,但是很多人理解不了,我在此处进行了总结,大家按我的思路看下去,肯定能理解。

  1. 使用蛮力法。最外循环为第i个数,第二循环从i开始一直到数组尾j,最内循环则计算i到j子数组的和。

    public static int maxSubArray(int arr[]) {
        int n = arr.length;
        int ThisSum = 0, MaxSum = 0;
        for(int i=0; i MaxSum) { MaxSum = ThisSum; }
            }
        }
        return MaxSum;
    }
    
  2. 该方式重复的计算了i到j之间值,重点在于如何减少重复的计算,在最内的k循环中,可以通过Sum[I, j] = Sum[I, j-1]+arr[j],这样就能避免重复的计算。

     public static int maxSubArray(int arr[]) {
         int size = arr.length;
         int maxSum = Integer.MAX_VALUE;
         for(int i=0; i maxSum) { maxSum = sum; }//这个判断是获取子序列的关键
             }
         }
         return maxSum;
     }
    
  3. 注意上面两个方案的叠进顺序,和对第二个解决方案的理解。动态优化依然是减少重复的运算。在上面的算法中,只消除了固定i下j的重复计算,但当i变化时,sum的部分值依然是重复的。那如何分解问题?若已知A[1, j]的最大子数组,那A[1, j+1]的最大子数组等于求解最后一个元素arr[n-1]与最大子数组的关系:①最大子数组包含arr[n-1],即以arr[n-1]结尾;②arr[n-1]单独构成最大子数组;③最大子数组不包含arr[n-1]。三种可能写为All[ i - 1] = max{arr[ i - 1 ], End[ i - 1 ], All[ i - 2 ]},三个选项分为对应①②③。End[i]是包含第i值的最大子数组,All[i]是当前最大子数组。

     public static int maxSubArray(int arr[]) {
         int n = arr.length;
         int End[] = new int[n];//End[i]表示包含当前值的最大子数组值
         int All[] = new int[n];//All[i]表示当前全局最大子数组值
         End[0] = All[0] = arr[0];//一开始全为arr[0]
         for(int i=1; i
  4. 上面每次只用到End[n-1]和All[n-1],这样只需要定义两个变量即可。

       public static int maxSubArray4(int arr[]) {
            int n = arr.length;
            int nAll = arr[0];
            int nEnd = arr[0];
            for(int i=1; i

你可能感兴趣的:(算法)