我正在做一个我无法解决的运动。我需要通过买卖比特币来获得最大的累积利润。我有一个函数(A,Y),该函数在一段时间内收到不同价格的A =数组,而Y =费用 限制:
注意:如果比特币在0时买入并在1时卖出,我们将损失A [1]-A [0] = 7050 -7200-Y = -200。因此,没有进行该动作。
注意2:您一次只能拥有1个比特币。要出售,您必须先购买。要购买,您需要什么都没有或之前没有出售。
注3:运动需要时间。您不能在A [5]买入和在A [4]卖出
注意4:如果无法盈利,则应返回0
复杂度为O(N)
A = [7200,7050,7300,7500,7440,7200,7300,7280,7400] //expected result 550
Y = 50
A[3] - A[1] - Y = 7500 - 7050 - 50 = 400
A[8] - A[5] - Y = 7400 - 7200 - 50 = 150
result = 550 //maximum accumulated profit
这就是我所拥有的
function solution(A, Y) {
if(A.length < 2) {
return 0;
}
var minIndex = (A[0] > A[1]) ? 1 : 0;
var minPrice = A[minIndex];
var acum = 0;
var i = minIndex + 1
for (i; i< A.length-1; i++) {
if( (A[i] - minPrice - Y) > (A[i+1] - minPrice - Y )) {
acum += A[i] - minPrice - Y;
i = i+1
} else {
acum += A[i + 1] - minPrice - Y;
i = i+2
}
minPrice = (A[i] > A[i+1]) ? A[i+1] : A[i];
}
return acum > 0 ? acum : 0;
}
实际上我要450,但应该是550
答案 0 :(得分:3)
它看起来似乎更加复杂,因为您需要检查所有可能的销售价格中的每个购买价格。
结果是一棵采用这种蛮力方法的树。
此解决方案仅返回所有买卖价格的最大利润。
function maxima(array, fee) {
function iter(prices, index, count) {
var i = 0, profit = 0;
if (index >= array.length) {
if (!prices.length || prices.length % 2) {
return;
}
if (prices.some((v, i, a) => i && (i % 2 ? a[i - 1] >= v : a[i - 1] < v))) {
return;
}
while (i < prices.length) {
profit += prices[i + 1] - prices[i] - fee;
i += 2;
}
if (!result.length || result[0].profit < profit) {
result = [{ profit, prices }];
} else if (result[0].profit === profit) {
result.push({ profit, prices });
}
return;
}
iter(prices.concat(array[index]), index + 1); // buy/sell
iter(prices, index + 1); // no action
}
var result = [];
iter([], 0, 0);
return result;
}
console.log(maxima([7200, 7050, 7300, 7500, 7440, 7200, 7300, 7280, 7400], 50));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:2)
(我相信Mark_M的回答在这里是最好的,但出于完整性考虑,我会离开我的。)
对于每个销售价格,我们希望知道其之前的最佳购买价格,因此我们可以将该销售与之前的最高累计价格配对。我们可以使用O(n^2)
算法,因为无论如何我们都必须返回。
function f(A, Y){
let m = [0].concat(new Array(A.length - 1));
for (let i=1; i<A.length; i++){
let smallest = A[i-1];
m[i] = m[i - 1];
for (let j=i-1; j>0; j--){
smallest = Math.min(smallest, A[j]);
if (smallest < A[i] + Y)
m[i] = Math.max(m[i], A[i] - smallest - Y + (m[j - 1] || 0));
}
}
return m[m.length - 1];
}
var a = [7200,7050,7300,7500,7440,7200,7300,7280,7400];
console.log(f(a, 50));
答案 2 :(得分:2)
我知道您已经有了答案,但是我想提出一个可能的O(n)解决方案。这个想法是,您可以监控价格走势以及本地的最小和最大价格。您可以随时在价格变化方向上定义一个方向变化,该变化相对于本地最小或最大值大于Y。您可以根据方向变化进行买卖。
var A = [6000, 7200, 7050, 7040, 7045, 7041, 7039, 7300, 7500, 7490, 7480, 7501, 7440, 7200, 7300, 7280, 7400];
var A = [7200, 7050, 7300, 7500, 7440, 7200, 7300, 7280, 7400];
let Y = 50
function buysell(A, Y) {
let direction = -1
let min = A[0]
let max = 0
let total = 0
for (let i = 1; i < A.length; i++) {
if (direction == -1) {
if (A[i] < min) min = A[i]
if (A[i] - min > Y) { // only change direction if change is greater than Y
direction = 1;
max = A[i]
console.log('buy at', min)
}
} else { // price is going up
if (A[i] > max) max = A[i]
if (max - A[i] > Y) {
total += max - min - Y
console.log('sell at ', max)
min = A[i]
direction = -1
}
}
}
// buy at end if price was going up
if (direction == 1) {
console.log('sell at ', max)
total += max - min - Y
}
return total
}
console.log("total: ", buysell(A, Y))
// Test with some edge cases:
var A = [6000, 7200,7050, 7040, 7045, 7041, 7039,7040, 7300,7500, 7490, 7480,7501, 7440,7200,7300,7280,7400];
console.log("total: ", buysell(A, Y))
var A = [ 7172, 2477, 4755, 2297, 2893, 8863 ]
console.log("total: ", buysell(A, Y))