问题是考虑到某一天的股票价格,最大化股票的利润。 我只能购买1支股票,卖出任何数字或什么都不做。
Test cases:
Input: 1 2 100
Output: 197
Explanation: Bought on day 1 and day 2 sold on day 3 total profit = (100 - 1) + (100 - 2) = 197
Input: 1 3 1 2
Output: 3
Explanation: buy one share on day 1, sell one on day 2, buy one share on day 3, and sell one share on day 4.
我在下面有一个递归解决方案,我知道还有其他解决方案,但我试图从递归的解决方案构建:
int maxProfit(vector<int> stock)
{
int profit = helper(stock, stock[0], 1, 1);
return profit < 0 ? 0 : profit;
}
int helper(vector<int>& stock, int cost, int index, int stockcount)
{
if (index == stock.size() - 1)
{
return (stock[index] * stockcount) - cost;
}
int buy = helper(stock, cost + stock[index], index + 1, stockcount + 1);
int sell = helper(stock, cost - stock[index], index + 1, stockcount - 1);
return max(buy, sell);
}
算法是否是正确的重新计算方法,有没有办法记住上述内容?可能会删除累加器cost
?
答案 0 :(得分:1)
您提供的递归解决方案似乎考虑了购买一只股票的选择,但忽略了无所作为的选择以及出售任意数量的自有股票的多种选择。
但最重要的是,它忽略了现实生活中最重要的优势:了解未来:)
如果您要从头到尾遍历数组,跟踪到目前为止的最高价格,请考虑一下如果:
(1)您遇到的价格是否低于您记录中的价格? (请记住,您的记录是未来价格)
和(2)您遇到的价格是否与您记录中的价格相同或更高? (再次请记住,您的记录中的价格是当前查看价格之后的最高价格)
(关于memoization - 一般来说,可以通过散列或为其参数集创建查找表来记忆函数的返回值,通过考虑哪些参数可以是常数或可以保持不变来进行优化,从而忽略如果您希望在计算过程中多次重复调用同一组参数,则记忆很有用。)
下面是一个JavaScript版本,其中包含您所描述的规则的记忆,然后是我在上面提到的O(n)
反向遍历。
Memoized recursion:
function maxProfit(stock){
return helper(stock, 0, 0, 0);
}
var hash = {};
function helper(stock, cost, index, stockcount){
let key = [cost, index, stockcount].join('-');
if (hash[key] !== undefined)
return hash[key];
if (index == stock.length)
return -cost;
var buy_or_not = helper(stock, cost + stock[index], index + 1, stockcount + 1);
for (let i=0; i<=stockcount; i++)
buy_or_not = Math.max(
buy_or_not,
helper(stock, cost - i*stock[index], index + 1, stockcount - i)
);
return hash[key] = buy_or_not;
}
console.log(maxProfit([1,1,50,1,1,50,1,1,40]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
O(n)
反向遍历:
function f(arr){
if (!arr.length)
return 0;
var i = arr.length - 1,
highest_sale_price = arr[i],
stock_count = 0,
current_cost = 0,
total_profit = 0;
for (i--; i>=0; i--){
// Wouldn't want to buy this
if (arr[i] >= highest_sale_price){
// Go back to the future and
// sell anything bought after
// this day at the next highest
// price
total_profit += stock_count * highest_sale_price - current_cost;
highest_sale_price = arr[i];
current_cost = 0;
stock_count = 0;
// Otherwise, we know a
// higher future price
// so buy this stock!
} else {
stock_count++;
current_cost += arr[i];
}
}
// Day 0, go back to the future and sell
// anything we have left at a higher price
if (highest_sale_price)
total_profit += stock_count * highest_sale_price - current_cost;
return total_profit;
}
console.log(f([1,1,50,1,1,50,1,1,40]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 1 :(得分:1)
术语: stock 是公司的特定所有权类别,例如英特尔的INTC或微软普通股的MSFT。您购买和销售的各个分区称为 shares 。
正如גלעדברקן已经指出的那样,你知道未来。没有猜测,没有美元平均,没有部分解决方案。您有完整的信息。
引理:如果出售1股股票是有意义的,那么卖出你所有的股票是有意义的。这将大大简化您的算法:您不必从1- N 中探索替代方案。
Lemma :如果今天的价格低于未来的最高价格,最好的策略是购买允许的最大价格。
<强>算法强>
// Base case:
If the array is empty, return
// Process
Find the maximum price in the array (call that day_s)
Buy max shares (one) on each day 1 : day_s
Sell all shares on day_s
(balance accounting is left as an exercise for the student)
// Recur
helper(stock[day_s: ], balance, 0)
答案 2 :(得分:0)
这是递归解决方案。在此解决方案中,我正在检查每个值i
,以查看是否找到了j
这样的值a[j] > a[i]
。然后,我将利润计算为a[j] - a[i]
,然后将利润添加到从索引j + 1
到e
的重复发生中。
int solve(int *a, int s, int e, int k){
// passing array a, starting index s, ending index e, max stocks one
// can sell k
// base case
if(s>=e)return 0;
if(k == 0)return 0;
int ans = 0;
for(int i = s; i<e; i++){
for(int j = i+1; j<=e; j++){
int temp =0;
if(a[j]>a[i]){
temp += a[j] - a[i] + solve(a,j+1,e,k-1);
}
ans = max(ans,temp);
}
}
return ans;
}