【Leecode 53】最大子序和(Java)
阿新 • • 發佈:2021-01-18
技術標籤:演算法
【題目描述】
給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
【樣例示例】
- 輸入:[-2,1,-3,4,-1,2,1,-5,4]
- 輸出:6
解釋:連續子陣列 [4,-1,2,1] 的和最大,為 6。
如果你已經實現複雜度為 O(n) 的解法,嘗試使用更為精妙的分治法求解。
【解題程式碼】
方法一:使用動態規劃
首先對陣列進行遍歷,變數count=0
儲存當前最大連續子序列和 ,max=nums[0]
為最大值
- 如果 count> 0,說明 count 對結果有增大效果,則保留count並加上當前的nums[i]
- 如果 count <= 0,說明 count 不能增大結果,需要捨棄,則 把count 更新為當前的nums[i]
- 每次比較 count 和 max 的大小,如果count>max,則將max更新為count的值
- 遍歷結束返回結果
時間複雜度:O(n)
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length==0){
return 0;
}
if(nums.length==1){
return nums[0];
}
int count=0,max=nums[0];
for(int i=0;i<nums.length;i++){
if(count > 0) {
count += nums[i];
} else {
count = nums[i];
}
max = Math.max(count,max);
}
return max;
}
}
方法二:分治法
分治法主要就是分類討論,將陣列分成三部分:
(1)[left, mid]
(2)[mid,mid+1]
(3)[mid+1,right]
時間複雜度:O(NlogN)
public class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
// 特判
if (len == 0) {
return 0;
}
return maxSubArraySum(nums, 0, len - 1);
}
private int maxSubArraySum(int[] nums, int left, int right) {
// 陣列只有一個數字情況
if (left == right) {
return nums[left];
}
int mid = (left + right) >> 1;
return max3(maxSubArraySum(nums, left, mid), // 計算左半邊
maxSubArraySum(nums, mid + 1, right), // 計算右半邊
maxCrossingSum(nums, left, mid, right));// 計算中間部分
}
// 比較左中右三個部分哪個最大
private int max3(int num1, int num2, int num3) {
return Math.max(num1, Math.max(num2, num3));
}
// 計算第二部分中間
private int maxCrossingSum(int[] nums, int left, int mid, int right) {
int sum = 0;
int leftSum = Integer.MIN_VALUE;
// 計算以 mid 結尾左半邊的最大的子陣列的和(包含 nums[mid])
for (int i = mid; i >= left; i--) {
sum += nums[i];
if (sum > leftSum) {
leftSum = sum;
}
}
sum = 0;
int rightSum = Integer.MIN_VALUE;
// 計算 mid+1 開始右半邊的最大的子陣列的和(不包含 nums[mid])
for (int i = mid + 1; i <= right; i++) {
sum += nums[i];
if (sum > rightSum) {
rightSum = sum;
}
}
return leftSum + rightSum;
}
}
個人感覺第一種比較簡單好理解一點,分治法也不是這道題的最優解。
【程式碼參考】