我覺得我和這個題型特別有緣阿,之前實習面試還被問到,然後這兩週的week competition都有出到,下面就從最原始的問題開始,然後慢慢講解其他有的沒的變形題目。
第二篇看這裡:[LeetCode]各種Max subarray問題-2
LeetCode 53. Maximum Subarray
題意: 從array裡面找一個subarray,使得該subarray有最大的和。
Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.
|
1. 暴力掃過: 枚舉所有可能的區段,找出最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public: int maxSubArray(vector& nums) { if(nums.empty()) return 0; int ans = nums[0]; for(int i = 0 ; i < nums.size() ; i++){ int temp = 0; for(int j = i ; j < nums.size() ; j++){ temp = temp + nums[j]; ans = max(ans, temp); } } return ans; } }; };
|
2. kadane’s algo
DP方法,DP[i]記錄了在i-th當下的max subarray,DP[i]只有兩種可能:
- DP[i] = arr[i]
- DP[i] = DP[i-1] + arr[i]
最後掃過一次DP取得最大的值即可。實際上,可以一邊掃一邊存最大值,如此就不用另外開一個DP array。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: int maxSubArray(vector& nums) { if(nums.empty()) return 0; int temp_max = nums[0]; int max_so_far = nums[0]; for(int i = 1 ; i < nums.size() ; i++){ temp_max = max(nums[i], temp_max+nums[i]); max_so_far = max(temp_max, max_so_far); } return max_so_far; } };
|
LeetCode 918. Maximum Sum Circular Subarray
題意: 從array裡面找一個subarray,使得該subarray有最大的和,但這個array是一個circular array。
Input: [5,-3,5] Output: 10 Explanation: Subarray [5,5] has maximum sum 5 + 5 = 10
|
1. kadane’s algo
有兩種case:
- max_sum_subarray在array中間,這時候直接用kadane’s algo
- max_sum_subarray在array的頭跟尾,這時要換個想法,把問題轉成total_sum - min_sum_subarray(也是用kadane’s algo去計算)
答案在這兩個case取最大值即可 ,但要注意如果array全部都是負數,此時total_sum - min_sum_array = 0,會得到錯誤的結果,這個case要特別處理(直接回傳max_sum_subarray)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public: int maxSubarraySumCircular(vector& A) { int temp_max = A[0]; int max_so_far = A[0]; int temp_min = A[0]; int min_so_far = A[0]; int total_sum = A[0]; for(int i = 1 ; i < A.size() ; i++){ temp_max = max(A[i], temp_max + A[i]); max_so_far = max(max_so_far, temp_max); temp_min = min(A[i], temp_min + A[i]); min_so_far = min(min_so_far, temp_min); total_sum += A[i]; } if(min_so_far == total_sum) return max_so_far; return max(max_so_far, total_sum-min_so_far); } };
|