53. Maximum Subarray
Problem
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
Code
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
int dp = nums[0];
for (int i = 1; i < nums.length; i++) {
// 如果dp<0就放弃dp
dp = Math.max(dp + nums[i], nums[i]);
max = Math.max(max, dp);
}
return max;
}
}
O(n) O(1)
class Solution {
public int maxSubArray(int[] nums) {
if(nums == null || nums.length == 0) return 0;
int res = nums[0];
int[] dp = new int[nums.length];
dp[0] = nums[0];
for(int i = 1; i < nums.length; i++){
dp[i] = nums[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
res = Math.max(res, dp[i]);
}
return res;
}
}
divide and conquer 解法, 并不是最优解
class Solution {
private int[] numsArray;
public int maxSubArray(int[] nums) {
numsArray = nums;
// Our helper function is designed to solve this problem for
// any array - so just call it using the entire input!
return findBestSubarray(0, numsArray.length - 1);
}
private int findBestSubarray(int left, int right) {
// Base case - empty array.
if (left > right) {
return Integer.MIN_VALUE;
}
int mid = (left + right) / 2;
int curr = 0;
int bestLeftSum = 0;
int bestRightSum = 0;
// Iterate from the middle to the beginning.
for (int i = mid - 1; i >= left; i--) {
curr += numsArray[i];
bestLeftSum = Math.max(bestLeftSum, curr);
}
// Reset curr and iterate from the middle to the end.
curr = 0;
for (int i = mid + 1; i <= right; i++) {
curr += numsArray[i];
bestRightSum = Math.max(bestRightSum, curr);
}
// The bestCombinedSum uses the middle element and the best
// possible sum from each half.
int bestCombinedSum = numsArray[mid] + bestLeftSum + bestRightSum;
// Find the best subarray possible from both halves.
int leftHalf = findBestSubarray(left, mid - 1);
int rightHalf = findBestSubarray(mid + 1, right);
// The largest of the 3 is the answer for any given input array.
return Math.max(bestCombinedSum, Math.max(leftHalf, rightHalf));
}
}
time: nlog(n) space: log(n)
打印 subarray 要求 subarray 的长度至少是 2
class Solution {
public List<Integer> maxSumWithK(int nums[], int k) {
int n = nums.length;
int maxSum[] = new int[n];
// 记录开始和结束的位置
int maxStart[] = new int[n];
maxSum[0] = nums[0];
int dp = nums[0];
int start = 0;
for (int i = 1; i < n; i++) {
if (dp < 0) {
maxStart[i] = i;
dp = nums[i];
} else {
dp += nums[i];
maxStart[i] = start;
}
maxSum[i] = dp;
}
// Sum of first k elements
int sum = 0;
for (int i = 0; i < k; i++) {
sum += nums[i];
}
// sliding window
// 确保有k这么长的window, 然后看加上maxSum是否结果会变大
int result = sum;
int resStart = 0;
int resEnd = k;
for (int i = k; i < n; i++) {
// Compute sum of k elements ending with a[i].
// i ~ i + k
sum = sum + nums[i] - nums[i - k];
// Update result if required
if (sum > result) {
resStart = i - k;
resEnd = i;
result = sum;
}
if (sum + maxSum[i - k] > result) {
resStart = maxStart[i - k];
resEnd = i;
result = sum + maxSum[i - k];
}
}
List<Integer> res = new ArrayList<>();
for (int i = resStart; i < resEnd; i++) {
res.add(nums[i]);
}
return res;
}
public static void main(String[] args) {
Solution solution = new Solution();
List<Integer> res = solution.maxSumWithK(new int[]{-1, 2, -100, 10, -300}, 3);
System.out.println(res);
}
}
按 <- 键看上一题!
52. N-Queens II
按 -> 键看下一题!
54. Spiral Matrix