您的位置:首页 > 其它

最大数字序列和问题,买卖股票问题,以及最长公共字串问题

2016-04-19 18:25 423 查看
  

最大数字序列和问题

最大数字序列和原理

给定由n个整数(可能为负整数)组成的序列A1,A2,A3,...,An,求该序列的连续子段的和的最大值。当所有整数均为负整数时定义其最大子段和为0

例如   {-4, 11,-2, 13,-7,-3,12} 的最大子段和为22

int MaxSum(int[] array,int n)
{
int b=0;
int sum=0;
for(int i=1;i<=n;i++)
{
if(b>0)
{
b+=array[i];
}
else
{
b=array[i];
}
if(b>sum)
{
sum=b;
}
}
return sum;
}

买卖股票问题:

点击打开链接


1,一次买卖股票受益最大

分析:此题就是选择买入卖出股票的最大收益,对于第i天卖出的最大收益即为第i天的股市价格减去[0,i-1]天内的最小股市价格,当第i天的股市价格比漆面最低股市价格还低,则更新最低股市价格。然后取最大的股市收益,为DP问题。用profit[i]表示第i天的收益,则minBuyPrice = min(minBuyPrice, prices[i]),并且profit[i] = prices[i]-minBuyPrice.   然后取profit中的最大值。

class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n == 0) return 0;
int maxPro = 0;
int minBuyPrice = prices[0];
for(int i = 1; i < n; i++){
minBuyPrice = min(minBuyPrice, prices[i]); // 用于记录当前天买进的最小值 minBuyPrice[i+1] = min(minBuyPrice[i], nums[i])
if(maxPro < (prices[i]- minBuyPrice)){ // 全局最大利益是否小于当天的利益
maxPro = prices[i]- minBuyPrice;
}
}
return maxPro;

}
};

2,不限制买卖次数,收益最大问题

此题是上题的变形,买入卖出的次数没有限制,但是第二次买入必须在第一次卖出的时间节点之后,,此时存在一个局部最优,即 2 4 5 3 6 8,此时8-2一定小于5-2+8-3,,因此就有取数组每次递增的收益即为局部最优,然后所有的局部最优加起来就是全局最优

法一(最简洁,干净,利落):

class Solution {
public:
int maxProfit(vector<int> &a) {
int profit = 0;
for (int i = 1; i < a.size(); ++i) {
if (a[i] > a[i-1]) {
profit += a[i]-a[i-1];
}
}
return profit;
}
};

法二:

class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n == 0) return 0;
int minBuyPrice = prices[0];
int sumResult = 0;
/*for(int i = 0; i < n; i++){
if(i+1 < n && prices[i] >= prices[i+1]){ // 局部最优在于当prices[i] >= prices[i+1]
sumResult += prices[i]-minBuyPrice; //既可用prices[i]-minBuyPrices了找到局部最优了--全部加起来就是全局最优解了
minBuyPrice = prices[i+1];
}else{
if(i+1 == n) sumResult += prices[i]-minBuyPrice;
}
}*/
for(int i = 1; i < n; i++){
if(prices[i] < prices[i-1]){ // 在i处有一个局部最优,所有的局部最优和就是全局最优
sumResult += prices[i-1]- minBuyPrice;
minBuyPrice = prices[i];
}
}
sumResult += prices[n-1]- minBuyPrice;
return sumResult;
}
};3,最多买卖两次股票受益最大问题
此题亦即变形,也就是求交易次数最多为两次。当然有两种方法,第一种暴力,对于每个i,我们求[0,i]与[i,n-1]两次收益,然后求和,遍历i,可以取其中的最大值,需要O(N^2)的时间。第二种方法是动态规划,用两个数组,第一个数组f1[i]用来表示在[0,i]内进行买入卖出的最大收益,用f2[i]表示在[i,n-1]内进行买入卖出的最大收益。然后最大收益即为max(f1[i]+f2[i]),如何求f1[i]和f2[i],,可参考上面的一次买卖股票问题。

class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n <= 1) return 0;
vector<int> f1(n); // 表示在[0,i]内进行买入卖出所能获得的最大profit
vector<int> f2(n); // 表示在[i, n-1]内进行买入卖出所能获得的最大profit 结果就为max(f1[i]+f2[i])

int minPrice = prices[0];

for(int i = 1; i < n; i++){
minPrice = min(minPrice, prices[i]);
f1[i] = max(f1[i-1], prices[i]- minPrice);
}

int maxPrice = prices[n-1];
for(int i = n-2; i >=0; i--){ // 这里要从后往前遍历
maxPrice = max(maxPrice, prices[i]);
f2[i] = max(f2[i+1], maxPrice - prices[i]);
}
int maxResult = 0;
for(int i = 0; i < n; i++)
maxResult = max(maxResult, f1[i]+f2[i]);
return maxResult;
}

};4,最多买卖k次股票问题
分析:此题为较难的动态规划问题。首先要第一步就是要转化成动态规划问题, 其次是要写出递归式。我们用local[i][j]表示第i天最多交易j次并且最后一次卖出在第j天所获得的最大利润;global[i][j]用来表示第i天最多交易j次所获得的最大利润。

那么local[i][j]的递归式为:

local[i][j] = max(global[i-1][j-1]+ max(diff, 0), local[i-1][j]+diff).

其中diff = prices[i] - prices[i-1];  global[i-1][j-1]表示第i-1天最多进行j-1次交易获得的最大利润,如果diff大于0,那么那么就加上今天获得利润,diff<0,那么最后一次就可以看做是当天买入并卖出。local[i-1][j]表示第i-1天最多进行j次交易获得的利润,加上diff就等于local[i][j]。 取两者最大值。

global[i][j]的递归式为:

global[i][j] = max(global[i-1][j], local[i][j]); 

也就是取第i-1天最多进行j次交易和第i天交易并且最多交易j次且最后一次交易在第i天的利润的最大值。

class Solution {
public:

int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if(k >= n/2) return maxProfit2(prices);
vector<int> lp(k+1);
vector<int> gp(k+1);
for(int i = 1; i < n; i++){
int diff = prices[i]- prices[i-1];
for(int j = k; j>0; j--){
lp[j] = max(gp[j-1]+max(diff, 0), lp[j]+diff);
gp[j] = max(gp[j], lp[j]);
}
}
return gp[k];

}
int maxProfit2(vector<int> &prices){
int ans = 0;
for(int i = 1; i < prices.size(); i++){
ans += max(prices[i]-prices[i-1], 0);
}
return ans;
}
};


最长公共子串问题

点击打开链接        点击打开链接

动态规划:如果X[i]==Y[j],那么dp[i][j]=dp[i-1][j-1]+1;

如果X[i]!=Y[j],那么dp[i][j]=0;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: