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維矩陣了採用降維角度處理。