给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
样例
给出数组[−2,2,−3,4,−1,2,1,−5,3]
,符合要求的子数组为[4,−1,2,1]
,其最大和为6
类似说法
面试题目:
公司给予你一次投资股票的机会,且已知股票的变化曲线图。希望你做出利益最大化选择
以下为简化信息:
a[] = {100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101,79, 94, 90, 97}(第1天~第17天,数值为每股售价)
应答思路:
要求利益最大化,即就是在股票售价最低时买进,最高时抛出。此时需要注意的问题是:
①在时间上,最低售价并不一定在最高售价的前面
②买进与售出价差额最大
接下来第一步:简单计算每天的股票涨浮情况
a[] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}
模型化题目:最大子数组问题
解决思路:
很容易想到利用累加法做,出现正值则为利润,负值为亏损。即为寻找最大正值
假如第一天买进,股票上涨13,第二天跌3,第三天跌25。这时候手中的股票已经大幅亏损,这时应当立即抛弃这个子数组。
我们这时候就想着,应该在股票买进手中之后,一直呈涨(正数)才是最理想的情况。
当sum = sum + a[x]; 寻找阶段性最大值sum并记录,当sum值为负数时抛弃这个子数组。重新赋值sum = 0;继续累加,通过每次阶段性最大值的比较,将最大值赋予max: max = sum
方法一:贪心法,复杂度O(n)(记住)
class Solution {
public:
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
int maxSubArray(vector<int> nums) {
// write your code here
int n = nums.size();
int ans = nums[0];
int sum = 0;
for(int i=0; i<n; i++)
{
sum += nums[i];
if(sum > ans)
{
ans = sum;
}
if(sum < 0)
{
sum = 0; //子串和为负数,丢掉
}
}
return ans;
}
};
最小子数组同理,代码如下:
class Solution {
public:
/*
* @param nums: a list of integers
* @return: A integer indicate the sum of minimum subarray
*/
int minSubArray(vector<int> &nums) {
// write your code here
int sum=0;
int minsum=nums[0];
int n=nums.size();
for(int i=0;i<n;i++)
{
sum=sum+nums[i];
if(minsum>sum)
minsum=sum;
if(sum>0)
sum=0;
}
return minsum;
}
};