【LeetCode】【分治法】連續數列(最大子序和)思路解析和程式碼

九筒-發表於2020-10-12

連續數列(最大子序和)

題目連結

個人思路

題意

求連續的最大子序和

個人思路程式碼

O(N)解法

  • 遍歷整個陣列,宣告變數ans儲存最大值,sum儲存當前和
  • 如果sum加上後一個元素 比後一個元素還小,則認為後一個元素時無效的並捨棄,並令sum值等於後一個元素的值
  • 否則就認為後一個元素是有效的,並加到sum上
  • 比較當前的sum值和ans的大小
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if(nums.size() == 1){
            return nums[0];
        }
        int ans = nums[0];
        int sum = nums[0];
        for(int i = 1; i < nums.size(); ++i)
        {
            if(sum + nums[i] <= nums[i])
            {
                sum = nums[i];
            }
            else
            {
                sum += nums[i];
            }
            if(sum > ans)
            {
                ans = sum;
            }
        }
        return ans;
    }
};

分治法

  • 劃分:將陣列劃分為左右子序列,當劃分到只剩一個元素時,最大子序和就是他本身(即遞迴出口)
  • 解決:對劃分的子序列求當前最大子序和(需要處理最大子序和可能在左子序中,也可能在右子序中,也可能在二者之間的某段)
  • 回溯:將當前的最大子序和返回

遞迴體:求左右子序列中的最大子序和,並通過比較得到最大子序和,若不在左右子序列中,則需計算出位於中間的最大子序和
遞迴出口:當左右指標相等時(即只剩一個元素時),最大子序和就是他本身,返回該元素

class Solution {
public:
 int inf = -1 * 0x3fffffff;
 int maxSubSum(vector<int>& nums, int left, int right){
        //特判
        if(nums.size() == 1){
            return nums[0];
        }
        //遞迴出口
        if(left == right){
		    return nums[left];
	    }
        int mid = (left + right) / 2;
        int leftSum = maxSubSum(nums, left, mid);
        int rightSum = maxSubSum(nums, mid + 1, right);
        //求左子序列的最大欄位和
        int sum1 = inf;
        int tempLeft = 0;
        for (int i = mid; i >= left; --i){
            tempLeft += nums[i];
            if(tempLeft > sum1){
                sum1 = tempLeft;
            }
        }
        //求右子序列的最大欄位和
        int sum2 = inf;
        int tempRight = 0;
        for(int i = mid + 1; i <= right; ++i){
            tempRight += nums[i];
            if(tempRight > sum2){
                sum2 = tempRight;
            }
        }
        //最大子序和在左子序列中
        if((sum1 + sum2 < leftSum) && (rightSum < leftSum)){
            return leftSum;
        }
        //最大子序和在右子序列中
        if(sum1 + sum2 < rightSum){
            return rightSum;
        }
        //最大子序和在二者之間
        return sum1 + sum2;
    }
    int maxSubArray(vector<int>& nums) {
        int len = nums.size();
        return maxSubSum(nums, 0, len - 1);
    }
};

相關文章