1. 程式人生 > >leetcode(17):連續子串和/乘積最大

leetcode(17):連續子串和/乘積最大

另一個比較常見的問題是,求連續子串的和/乘積最大。

1.leetcode#53. Maximum Subarray

1.1題目描述

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個數),返回其最大和。
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

1.2思路

這同樣是一個動態規劃的題目。我們只需要一個區域性最大值,然後一個全域性最大值即可。關鍵是區域性最優值的來源是什麼。主要有2,1是當前值,另一個是之前的區域性最大值+當前值。那麼看區域性最大值是來源於哪即可,然後再和全域性最優進行比較。

1.3程式碼

public int maxSubArray(int[] nums) {
        if(nums==null||nums.length==0) return 0;
        #全域性最大
        int max=Integer.MIN_VALUE;
        #區域性最大
        int
tempmax=0; for(int i=0;i<nums.length;i++){ tempmax=tempmax+nums[i]; //狀態轉移 tempmax=tempmax>nums[i]?tempmax:nums[i]; //和全域性比較 max=max>tempmax?max:tempmax; } return max; }

2.leetcode#152. Maximum Product Subarray

2.1題目描述

Find the contiguous subarray within an array (containing at least one number) which has the largest product.
找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

2.2思路

和第一題思路一樣,只不過這裡要考慮正負值,因為負負得正,這樣最小值有可能直接變成最大值了。

2.3程式碼

public int maxProduct(int[] nums) {
        if(nums==null){
            return 0;
        }
        int max=nums[0];
        int min=nums[0];
        int globalmax=nums[0];
        //int globalmin=nums[0];
        for(int i=1;i<nums.length;i++){
            int tempmax=max*nums[i];
            int tempmin=min*nums[i];
            //如果最小值和最大值互換了
            if(tempmin>tempmax){
                int temp=tempmax;
                tempmax=tempmin;
                tempmin=temp;
            }
            //區域性最大,區域性最小
            max=tempmax>nums[i]?tempmax:nums[i];
            min=tempmin<nums[i]?tempmin:nums[i];
            //全域性最大
            globalmax=globalmax>max?globalmax:max;
            //全域性最小
            //globalmin=globalmin<min?globalmin:min;
        }
        return globalmax;
    }

3.子矩陣最大累加和

3.1問題描述

給定一個矩陣Matrix, 其中的值由正, 有負, 有0, 返回子矩陣的最大累加和.

3.2思路

這個思路和第一題一樣,只不過現在從1維變為2維了,我們由第一題可以知道,最大連續子串和的時間複雜度維O(n),那麼二維遍歷一次,也應當是O(n^2),因此最少也要O(n^3)才能完成。
我們首先考慮第一層的最大累加和,如同第一題一樣就可以解決。隨後在判斷第一層和第二層一起的最大累加和,即把第一層和第二層按位加,就變成了1維的,然後同樣採取第一題的做法。以此類推,直到加為最後一層即可。然後找到最大值,如果還需要記錄該矩陣的大小,就在每次遍歷時,加入當前遍歷次數和當前最優的連續數目即可,最終再進行一個乘積運算。

3.1程式碼

public static int MaximumSum(int[][] Matrix){
        int max=Integer.MIN_VALUE;
        for(int i=0;i<Matrix.length;i++){
            int[] sum=new int[Matrix[0].length];
            for(int j=i;j<Matrix.length;j++){
                //進行累加
                for(int col=0;col<Matrix[0].length;col++){
                    sum[col]+=Matrix[j][col];
                }
                int tempmax=maxSubArray(sum);
                max=max>tempmax?max:tempmax;
            }
        }
        return max;
    }

其實變成向量的乘積,也是這個道理,只不過把累加變成累乘即可。

4.小結

這次我們主要講解了連續子串最大和和連續乘積最大和的問題,另外把一維向量變為2維矩陣了採用降維角度處理。