程序员面试金典——解题总结: 9.17中等难题 17.8给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和

时间:2024-11-21 09:26:11
  • #include <iostream>
  • #include <>
  • #include <vector>
  • using namespace std;
  • /*
  • 问题:给定一个整数数组(有正数有负数),找出总和最大的连续数列,并返回总和
  • 分析:这个是动态规划问题,采用前缀和的方式来解决。
  • 设dp[i]表示以元素A[i]结尾的最大连续子序列之和
  • 最大连续子序列和的产生方式不过两种:
  • 1】是通过以A[i-1]结尾的最大连续子序列之和 + A[i]形成的
  • 2】前面A[i-1]结尾的最大连续子序列之和小于0,直接抛弃,重新选择A[i]作为最大连续子序列之和
  • 所以有dp[i] = max{dp[i-1] + A[i] , A[i]}
  • dp[0] = A[0]
  • 而且需要记录最大连续子序列之和的起始位置,设数组paths,
  • paths[i]表示以dp[i]结尾的最大连续子序列和的起始位置
  • 输入:
  • 9(数组元素个数n,下一行输入n个元素)
  • 3 -4 5 7 -1 2 6 1 -13
  • 输出:
  • 20(最大连续子序列和)
  • 5 7 -1 2 6 1(最大连续子序列)
  • */
  • int maxSubsequenceSum(vector<int>& datas ,vector<int>& dp, vector<int>& paths , int& maxEndIndex)
  • {
  • if(datas.empty())
  • {
  • throw("No data");
  • }
  • int size = datas.size();
  • int max = INT_MIN;
  • int maxIndex = -1;
  • for(int i = 0 ; i < size ; i++)
  • {
  • if(i)
  • {
  • if( dp[i-1] <= 0 )
  • {
  • dp.at(i) = datas.at(i);
  • paths.at(i) = i;
  • }
  • else
  • {
  • dp.at(i) = dp.at(i-1) + datas.at(i);
  • paths.at(i) = i - 1;
  • }
  • }
  • else
  • {
  • dp.at(i) = datas.at(i);
  • paths.at(i) = i;
  • }
  • if(dp.at(i) > max)
  • {
  • max = dp.at(i);
  • maxIndex = i;
  • }
  • }
  • maxEndIndex = maxIndex;
  • return max;
  • }
  • void printPath(vector<int>& paths , int maxEndIndex , vector<int>& datas)
  • {
  • if(paths.empty())
  • {
  • return;
  • }
  • if(-1 == maxEndIndex)
  • {
  • return;
  • }
  • //如果递归后寻找的路径下标相同,说明应该截止了
  • if(-1 != maxEndIndex && maxEndIndex == paths[maxEndIndex])
  • {
  • cout << datas.at(maxEndIndex) << " ";
  • return;
  • }
  • int value = paths[maxEndIndex];
  • printPath(paths , value , datas);
  • cout << datas.at(maxEndIndex) << " ";
  • }
  • void process()
  • {
  • int num;
  • vector<int> datas;
  • vector<int> paths;
  • vector<int> dp;//存放最大连续子序列和
  • int value;
  • int maxEndIndex = 0;
  • while(cin >> num)
  • {
  • datas.clear();
  • paths.clear();
  • dp.clear();
  • for(int i = 0 ; i < num ; i++)
  • {
  • cin >> value;
  • datas.push_back(value);
  • paths.push_back(-1);
  • dp.push_back(0);
  • }
  • int result = maxSubsequenceSum(datas, dp , paths , maxEndIndex);
  • cout << result << endl;
  • printPath(paths , maxEndIndex , datas);
  • cout << endl;
  • }
  • }
  • int main(int argc , char* argv[])
  • {
  • process();
  • getchar();
  • return 0;
  • }