首页 > 试题广场 >

黄金投资

[编程题]黄金投资
  • 热度指数:509 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

给定一个数组表示黄金的每天价格走势,数组中第i个元素表示第i+1天黄金的价格。

设计一个算法找到投资黄金的最大利润。你最多只能完成两笔交易(两次买入和卖出)。

 

例子: price = [1, 2, 8, 3, 5, 7]

如:黄金第一天的价格为1,第六天的价格为7

第一次交易:第一天买入,第三天卖出,赚取利润为7

第二次交易:第四天买入,第六天卖出,赚取利润为4

两笔交易共赚取利润为11

 

注意:在你再次购买黄金时,必须卖出所有黄金

因此:

第一次交易:第一天买,第三天卖

第二次交易:第二天买,第六天卖是不允许的,因为第二天还没卖出所有黄金

 

输入描述

Int型的数组

 

输出描述

Int型的最大利润

 

输入例子

[1, 2, 8, 3, 5, 7]

 

输出例子

11

示例1

输入

[1, 2, 8, 3, 5, 7]

输出

11
Python版本,复杂度爆炸,供参考
class Solution:
    def maxProfit(self, prices):
        n = len(prices)
        max_sum = 0

        for i in range(n-3):
            for j in range(i+1, n-2):
                sum1 = 0
                sum1 = prices[j] - prices[i]

                for k in range(j+1, n-1):
                    for l in range(k+1, n):
                        sum2 = 0
                        sum2 = prices[l] - prices[k]

                        max_sum = max(sum1+sum2, max_sum)
                    l = 0
            j = 0

        return max_sum

list1 = eval(input())

aa = Solution()
print(aa.maxProfit(list1))


发表于 2022-03-21 11:27:58 回复(0)

很简单的题目,不知道为什么没有人抄近道。
最多买卖两次且两次买卖没有交集,因此维护前缀最大差,后缀最大差,并枚举分割点即可。复杂度O(n)。

class Solution:
    def maxProfit(self , prices ):
        n = len(prices)
        prices = [0] + prices
        pred = [0] * (n + 5)
        suff = [0] * (n + 5)
        MiN = 100000000
        for i in range(1, n + 1) :
            pred[i] = max(pred[i - 1], prices[i] - MiN)
            MiN = min(MiN, prices[i])
        MaX = -100000000
        for i in range(n, 0, -1) :
            suff[i] = max(suff[i + 1], MaX - prices[i])
            MaX = max(MaX, prices[i])
        ans = 0
        for i in range(1, n + 1) :
            ans = max(ans, pred[i] + suff[i + 1])
        return ans
发表于 2021-05-18 20:27:31 回复(0)
找到所有上升区间,极差最大的两个区间就是我们两次需要买入和卖出的时间。当然,一个数组中最大和次大的两个数可以在O(n)的复杂度求出来,但是笔试题懒得写了😂
class Solution:
    def maxProfit(self , prices):
        # write code here
        n = len(prices)
        start_points = []
        for i in range(n - 1):
            if i == 0:
                start_points.append(i)
            if prices[i] > prices[i + 1]:
                start_points.append(i + 1)
        start_points.append(n)
        diff = []
        for i in range(len(start_points) - 1):
            if start_points[i] < start_points[i + 1]:
                diff.append(prices[start_points[i + 1] - 1] - prices[start_points[i]])
        return sum(sorted(diff, reverse=True)[:2]) if diff else 0

发表于 2021-04-12 13:17:40 回复(0)
class Solution {
public:
    /**
     * 黄金投资
     * @param prices int整型一维数组 价格
     * @param pricesLen int prices数组长度
     * @return int整型
     */
    int maxProfit(int* prices, int pricesLen) {
        // write code here
        int interest=0;
        int max=0;
        for(int i=0;i<pricesLen;i++){
            for(int j=i;j<pricesLen;j++){
                for(int k=j;k<pricesLen;k++){
                    for(int l=k;l<pricesLen;l++){
                        
                        interest=prices[j]-prices[i]+prices[l]-prices[k];
                        if(max<interest){
                            max=interest;
                        }
                    }
                }
            }
        }
        return max;
    }
};

发表于 2022-02-19 21:11:08 回复(0)

LeetCode 买卖股票的最佳时机 III

class Solution {
public:
    int maxProfit(int* prices, int pricesLen) {
        int buy1 = INT_MIN, sell1 = 0;
        int buy2 = INT_MIN, sell2 = 0;
        for (int i = 0; i < pricesLen; ++i) {
            buy1 = max(buy1, -prices[i]);
            sell1 = max(sell1, buy1 + prices[i]);
            buy2 = max(buy2, sell1 - prices[i]);
            sell2 = max(sell2, buy2 + prices[i]);
        }
        return sell2;
    }
};
编辑于 2022-01-17 22:31:46 回复(0)
public int maxProfit(int[] prices)
{ int n = prices.length;  int[] pred = new int[n];  int[] suff = new int[n];  int min = prices[0];  int max = prices[n-1];  //从前往后递归,每个pred[i]表示到i为止,最大的收益  for (int i = 1; i < n; i++) {
        pred[i] = Math.max(pred[i-1],prices[i]-min);
       min = Math.min(min,prices[i]);  } //从后往前,每个suff[i]表示从n-1  i 为止的最大收益  for (int i=n-2;i>=0;i--)
    {
        suff[i] = Math.max(suff[i+1],max-prices[i]);  max = Math.max(max,prices[i]);  } int ans = 0;  //pred[i]+ suff[i]表示0-ii-n-1这两段的最大收益的和  for (int i=0;i<n;i++)
    {
        ans = Math.max(ans,pred[i]+suff[i]);  } return ans; }

编辑于 2021-09-13 20:45:55 回复(0)
class Solution {
public:
    /**
     * 黄金投资
     * @param prices int整型一维数组 价格
     * @param pricesLen int prices数组长度
     * @return int整型
     */
    int maxProfit(int* prices, int pricesLen) {
        // write code here
        // 1 - 准备阶段
        vector<int> maxDict;

        
        // 2 - 得到结果
        // 得到第一个差距最大的增序列
        int maxPro1 = 0;
        int left = 0, right = 0;
        while(right<pricesLen){
            if(right+1<pricesLen && prices[right]<=prices[right+1]){
                right++;
            }else if(right+1 == pricesLen){
                maxDict.push_back(prices[right]-prices[left]);
                right++;
            }else{
                maxDict.push_back(prices[right]-prices[left]);
                right++;
                left = right;
            }
        }
        sort(maxDict.begin(), maxDict.end(), greater<int>());
        
        // 3 - 输出结果
        return maxDict[0]+maxDict[1];
    }
};

暴力算法,笔试就这么写了,时间复杂度肯定不是最优的,但是方便😂
动态规划找出所有子连续升序列,然后记录每一个子生序列的最大值与最小值的差,然后压入一个vector,
最后对vector进行降序排列,第0个加第一个就是结果了
发表于 2021-04-24 10:59:36 回复(0)
思路:最多可以买卖两次,则可以遍历第三个价格以后所有价格作为分界点,即为,0-i, i-n 两个子串(遍历到最后则为0-n)。问题则变为分别求两个子串的最大投资值,然后求他们的最大的和。
max_son中,对子串价格遍历,记录买的价格,如果后续出现价格比原来的买价小,则再调用求子串的最大投资;否则,以当前价-buy与前面的最大利润比较,取大值。
#
# 黄金投资
# @param prices int整型一维数组 价格
# @return int整型
#
class Solution:
    def maxProfit(self , prices ):
        # write code here
        length = len(prices)
        max_pro = 0
        for i in range(3, length):
            max_pro = max(max_pro, self.max_son(prices, 0, i) + self.max_son(prices, i, length))
        return max_pro
        
    def max_son(self, prices, x, y):
        max_pro_son = 0
        buy = prices[x]
        # sell = 0
        for i in range(x, y):
            if buy>prices[i]:
                max_pro_son = max(max_pro_son, self.max_son(prices, i, y))
            else:
                max_pro_son = max(max_pro_son, prices[i]-buy)
        return max_pro_son


发表于 2021-04-21 20:27:39 回复(0)
因为最多两次交易,所以应该枚举某一天,在这一天之前有一次交易,这一天之后有一次交易。
利用最大字段和的思路从1-n枚举第i天前进行一次交易的最大利益,从n-1反向枚举第i天之后交易一次的最大收益。
在枚举第i天前后的最大收益和。需要注意收益初值应为0,好应对3 2 1 这种降序。
class Solution {
public:
    /**
     * 黄金投资
     * @param prices int整型一维数组 价格
     * @param pricesLen int prices数组长度
     * @return int整型
     */
    int maxProfit(int* prices, int pricesLen) {
        int i,j,ans=0,minv=prices[0],a[pricesLen],b[pricesLen];
        a[0]=b[pricesLen-1]=0;
        for(i=1;i<pricesLen;i++)
        {
            a[i]=max(a[i-1],prices[i]-minv);
            minv=min(minv,prices[i]);
        }
        int maxv=prices[pricesLen-1];
        for(i=pricesLen-2;i>=0;i--)
        {
            b[i]=max(b[i+1],maxv-prices[i]);
            maxv=max(maxv,prices[i]);
        }
        for(i=0;i<pricesLen;i++)
            ans=max(ans,a[i]+b[i]);
        return ans;
    }
};


发表于 2021-04-17 11:47:51 回复(0)
class Solution:
    def maxProfit(self , prices):
        try:
            n = len(prices)
            if n == 1:
                result1 = 0
            else:
                result = []
                for i in range(1,n,1):
                    lines1 = prices[0:i]
                    lines2 = prices[i:n]

                    nlines1 = sorted(lines1)
                    nlines2 = sorted(lines2)

                    a = nlines1[0]
                    b = nlines1[-1]
                    if lines1.index(a) == i:
                        nlines1.remove(a)
                    if lines1.index(b) == 0:
                        nlines1.remove(b)
                    
                    while True:
                        if len(nlines1) <= 1:
                            max1 = 0
                            break
                        a = nlines1[0]
                        b = nlines1[-1]
                        if lines1.index(a)<lines1.index(b):
                            max1 = b-a
                            break
                        else:
                            nlines1.remove(b)
                            
                    c = nlines2[0]
                    d = nlines2[-1]
                    if lines2.index(d) == 0:
                        nlines2.remove(d)
                    if lines2.index(c) == n-1-1:
                        nlines2.remove(c)
                    
                    while True:
                        if len(nlines2) <= 1:
                            max2 = 0
                            break
                        c = nlines2[0]
                        d = nlines2[-1]
                        if lines2.index(c)<lines2.index(d):
                            max2 = d-c
                            break
                        else:
                            nlines2.remove(d)
                        
                        
                    result.append(max1+max2)
                    result1 = max(result)
        except:
            return(0)
        else:
            return(result1)
                
发表于 2021-04-13 12:19:39 回复(0)
计算所有的价格上升区间,得到差值,取最大和第二大值即可
发表于 2021-04-10 23:04:38 回复(0)