/*
線性DP問題 leetcode 53
給你一個整數數組 nums ,請你找出一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
子數組是數組中的一個連續部分。
示例 1:
輸入:nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出:6
解釋:連續子數組 [4,-1,2,1] 的和最大,為 6 。
示例 2:
輸入:nums = [1]
輸出:1
示例 3:
輸入:nums = [5,4,-1,7,8]
輸出:23
設 dp[i] 表示以第 i 個元素結尾的連續子數組的最大和。對于每個元素 nums[i],有兩種選擇:
將 nums[i] 加入到以 nums[i-1] 結尾的連續子數組中。
以 nums[i] 作為新的連續子數組的起點。
因此,狀態轉移方程為:
dp[i] = max(dp[i-1] + nums[i], nums[i])
同時,我們需要記錄最大和以及對應的子數組的起始和結束位置。
*/
#include <iostream>
#include <vector>
using namespace std;
// 函數用于找出具有最大和的連續子數組
pair<int, vector<int>> maxSubArray(vector<int>& nums) {
int n = nums.size();
if (n == 0) return {0, {}}; // 如果數組為空,直接返回 0 和空數組
// {-2, 1, -3, 4, -1, 2, 1, -5, 4}
int maxSum = nums[0]; // 記錄最大和
int currentSum = nums[0]; // 記錄當前以當前元素結尾的連續子數組的最大和
int start = 0, end = 0; // 記錄最大和子數組的起始和結束位置
int tempStart = 0; // 臨時記錄起始位置
for (int i = 1; i < n; i++) {
// 根據狀態轉移方程更新當前和
if (currentSum + nums[i] > nums[i]) {
currentSum += nums[i];
} else {
currentSum = nums[i];
tempStart = i; // 更新臨時起始位置
}
// 更新最大和以及對應的起始和結束位置
if (currentSum > maxSum) {
maxSum = currentSum;
start = tempStart;
end = i;
}
}
// 提取最大和子數組
vector<int> subArray(nums.begin() + start, nums.begin() + end + 1);
return {maxSum, subArray};
}
int main() {
vector<int> nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
pair<int, vector<int>> result = maxSubArray(nums);
cout << "最大和: " << result.first << endl;
cout << "最大和子數組: ";
for (int num : result.second) {
cout << num << " ";
}
cout << endl;
return 0;
}