问题:
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
我的解答:(超时的暴力算法,没有ac)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0;
reverse(prices.begin(), prices.end());
int maxdiff = 0;
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
if ((prices[i] - prices[j])>maxdiff)
{
maxdiff = prices[i] - prices[j];
}
}
}
return maxdiff;
}
};
解释:对于问题来说,这道题的意思就是vector中的两数最大差值,而且大值在小值后面。这种方法就是一个个试,先把vector元素调转,然后一个个从前往后减。超时错误。
后来看了别人用动态规划法。感觉挺好。刚开始学动归的时候,觉得很难很怕,其实不用怕,慢慢一点一点学就好了。
我的解答2(动态规划):
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0) return 0;
int maxdiff=0;
int minleft = prices[0];
for (int i = 1; i <prices.size(); i++)
{
if (minleft > prices[i - 1])
{
minleft = prices[i - 1];
}
if (maxdiff < ( prices[i]-minleft))
{
maxdiff = prices[i]- minleft ;
}
}
return maxdiff;
}
};
8ms 20.74%
解释:这个的思路很简单,就是一步一步来,不断地扩充问题规模,直到问题规模为原问题规模位置。在这里就是,找出左边最小的值,然后看新的加进来的元素与之作差,是不是比原最大差值大,假如是,就更新最大差值。同时,也要注意更新最小左边的值。
把一个问题从小解决,不断加入新元素,加入一个新元素就再解决一次,以此类推。这个问题的简单之处在于,它只需要查询上一个规模的问题的解决方案,不需要查询上上个,所以只用变量就可以存储问题,无需存储一个表。
做这题的时候,就感觉动态规划法给自己的启示还是很大的,人也是这样,一步一步走,踏踏实实地,一步一个脚印,就能走得快了。
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==0) return 0;
int maxdiff=0;
int minleft = prices[0];
for (int i = 1; i <prices.size(); i++)
{
if (minleft > prices[i - 1])
{
minleft = prices[i - 1];
}
if (maxdiff < ( prices[i]-minleft))
{
maxdiff = prices[i]- minleft ;
}
}
return maxdiff;
}
};
后面看到了一种Kadane’s Algorithm算法,使用java实现的,我觉得思想也很好,而且可以用来计算最大子串问题。
public int maxProfit(int[] prices) {
int maxCur = 0, maxSoFar = 0;
for(int i = 1; i < prices.length; i++) {
maxCur = Math.max(0, maxCur += prices[i] - prices[i-1]);
maxSoFar = Math.max(maxCur, maxSoFar);
}
return maxSoFar;
}
解释:
*maxCur = current maximum value
*maxSoFar = maximum value found so far
他的思路是这样的。也是一次扩大一个元素的规模。然后计算新的元素与上一个元素的差值。假如下一个值是令总差值增加的,那么就更新最大差值,假如是减少的总差值的,那么总差值不变。假如加入了这个值是令现有差值变负的,那么减少太多了,没有必要留着这个值,那么就从这个值开始再开始新的计数,相当于以这个令现有差值变负的值开始一段新的技术,新的计数也跟就得总差值比,直到比总差值大才更新。这里面有一种分段计算的思想。