盘点面试5道买卖股票,文末送复习资料PDF啦

217 阅读4分钟

If you wish to survive, you need to cultivate a strong mental attitude.
如果你想活着,需要培养一颗坚强的心。

概述

盘点面试中常问的买卖股票的哪些题,程序哥这里整理出来并附上答案了,文末有程序哥在春招和秋招过程中整理的面试常见问题的PDF,欢迎公众号后台留言,免费赠送!!!

  • 买卖股票的最佳时机【只能1次】
  • 买卖股票的最佳时机【可2次】
  • 买卖股票的最佳时机【不限次】
  • 买卖股票的最佳时机【含冷冻期】
  • 买卖股票的最佳时机【含手续费】
  • 两人轮流在桌子上放硬币,谁会胜利【附加题】

1 买卖股票的最佳时机【只能1次】

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。
输入: [7,1,5,3,6,4]
输出: 5

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

答案

只需要关心当前值和历史最小值,就可以了。
public static int maxProfit(int[] prices) {
    int result = 0;
    int min = Integer.MAX_VALUE;
    for (int num : prices) {
        min = Math.min(min, num);
        result = Math.max(result, num - min);
    }
    return result;
}

2 买卖股票的最佳时机【可2次】

核心:就当是同一天买卖,两次,

答案

 public int maxProfit(int[] prices) {
    int minPrice1 = Integer.MAX_VALUE;         
    int maxProfit1 = 0;                        
    int maxProfitAfterBuy = Integer.MIN_VALUE; 
    int maxProfit2 = 0;                        
    for(int price : prices) {
        // 1.第一次最小购买价格
        minPrice1  = Math.min(minPrice1,  price);

        // 2.第一次卖出的最大利润
        maxProfit1 = Math.max(maxProfit1, price - minPrice1);

        // 3.第二次购买后的剩余净利润
        maxProfitAfterBuy  = Math.max(maxProfitAfterBuy,  maxProfit1 - price );

        // 4.第二次卖出后,总共获得的最大利润(第3步的净利润 + 第4步卖出的股票钱)
        maxProfit2 = Math.max(maxProfit2, price + maxProfitAfterBuy);
    }
    return maxProfit2;
}

3 买卖股票的最佳时机【不限次】

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
输入: [7,1,5,3,6,4]
输出: 7

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3

答案

// 多次
public static int maxProfit(int[] prices) {
    int res = 0;
    // 多次买卖,利润最大的话,就需要在每相连的上升阶段买卖就可以了
    for(int i =0; i <prices.length-1; i++){
        if(prices[i+1] - prices[i] > 0){
            res += prices[i+1] - prices[i];
        }
    }
    return res;
}

4 买卖股票的最佳时机【含冷冻期】

卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

答案

public static int maxProfit(int[] prices) {
    if (prices.length == 0) {
        return 0;
    }
    // 定义三个数组 表示三种状态,
    int n = prices.length;
    int[] A = new int[n];// 观望 第iA状态的最佳利润
    int[] B = new int[n]; // 持股-prices
    int[] C = new int[n]; // 冷却+prices
    A[0] = 0;
    B[0] = C[0] - prices[0];
    for (int i = 1; i < n; i++) {
        // 变为A状态有两种,a-A 和 c-a
        A[i] = Math.max(A[i - 1], C[i - 1]);
        //变为B状态有两种,b-b,A-b
        B[i] = Math.max(B[i - 1], A[i - 1] - prices[i]);
        // 变为C只有一种情况
        C[i] = B[i - 1] + prices[i];
    }
    return Math.max(A[n - 1], C[n - 1]);
}

5 买卖股票的最佳时机【含手续费】

输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
输出: 8
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

答案

public static int maxProfit(int[] prices, int fee) {
    int len = prices.length;
    if (len < 2) {
        return 0;
    }
    // dp[i][j] 表示【0,i】区间内,到第1天状态为j时候的最大收益
    //j = 0 表示不持股,j = 1表示持股 
    int[][] dp = new int[len][2];
    dp[0][0] = 0; // 不持股
    dp[0][1] = -prices[0] - fee; //持股
    for (int i = 1; i < len; i++) {
        dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
        dp[i][1] = Math.max(dp[i-1][1], dp[i][0] -prices[i] - fee);
    }
    return dp[len-1][0];
}

6 两人轮流在桌子上放硬币,谁会胜利

两个人在圆桌子上轮流下硬币,规定最后一个人下硬币的时候并且刚好占满桌面,问是否有必胜的方法?

答案 其实很简单哈,只要第一个下硬币,并且放在桌子的正中心,之后根据对称性,可以保障第一个人必赢。

面经PDF分享

  • 公众号后台回复【加群】,程序哥看到后会第一时间分享。

本文使用 mdnice 排版