1. 程式人生 > >LeetCode刷題Easy篇Best Time to Buy and Sell Stock

LeetCode刷題Easy篇Best Time to Buy and Sell Stock

題目

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 (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

我的嘗試

分解為下面的問題:一個數組,求最大差值,並且小的靠前,大的靠後,不要求相鄰。程式碼如下:

class Solution {
    public int maxProfit(int[] nums) {
        int max=0;
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[j]-nums[i]>max&&nums[j]>nums[i]){
                    max=nums[j]-nums[i];
                } 
            }   
        }
        if(max<0){
            return 0;
        }
        return max;
        
        
    }
}

程式碼通過leetcode,測試但是效率不高,時間複雜為O(n2),是否有可以優化的方法?回憶一下我處理O(n)的一些方法:

1 空間換時間

2 利用動態規劃,利用之前的結果 ---沒有發現重複比較,感覺無法利用之前的比較結果

3 兩個指標方法-----可以嘗試

我的嘗試2

嘗試用兩個指標進行比較,一次迴圈,降低時間複雜度。還是需要兩次迴圈。沒有成功

優化解法

看了solution,發現這個思路很厲害!但是不通用,後來discuss板塊有人提出了kadane演算法,以前一道題有人提出過這個演算法,所以打算利用這個更加通用的演算法解決。

先來學習一下什麼是kandane演算法:

Kandane演算法用來求解“連續子陣列的最大和”,給定一個數組,求最長的連續子陣列,和是最大的。

def max_subarray(A):
    max_ending_here = max_so_far = A[0]
    for x in A[1:]:
        max_ending_here = max(x, max_ending_here + x)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

來,走一個kandane演算法,求一個整型陣列,連續子陣列的最大和是多少?

package com.puhui.goosecard.manage;

/**
 * 2 * @Author: kerry
 * 3 * @Date: 2018/12/7 10:18
 * 4
 */
public class Test {


    public static int kandane(int[] nums) {
        int currMax = nums[0];
        int maxSoFar = nums[0];
        //注意從1開始
        for (int i = 1; i < nums.length; i++) {
            currMax = Math.max(nums[i], currMax + nums[i]);
            maxSoFar = Math.max(currMax, maxSoFar);
        }
        return maxSoFar;

    }


    public static void main(String[] args) {
        int[] nums = {2, 4, 0, -4, 6, -8, 1};
        System.out.println(kandane(nums));

    }
}

如何列印這個陣列呢?那天子陣列問題,看看怎麼解決,先留一個問題。

我們回到當前的題目。看看如何利用kandane演算法解決。

比如我們求[7,1,5,3,6,4],某兩個元素,差值最大,不必需相鄰。轉換為相鄰元素的差值陣列,第一個元素差值為0.如下:

[0,-6,4,-2,3,-2],差值最大,其實就是求這個差值陣列的連續最大和,不是嗎,完美轉為kandane演算法的解決思路。

因為第一個元素差值為0,所以程式碼maxCurr和maxSofar初始值都為0.

package com.puhui.goosecard.manage;

/**
 * 2 * @Author: kerry
 * 3 * @Date: 2018/12/7 10:18
 * 4
 */
public class Test {


    public static int kandane(int[] nums) {
        int currMax = 0;//注意點,是0,不是nums[0]
        int maxSoFar = 0;
        //注意從1開始
        for (int i = 1; i < nums.length; i++) {
            //-優先順序高,搞錯了,注意比較物件是0,不是nums[i]
            currMax = Math.max(0, currMax += nums[i] - nums[i - 1]);
            maxSoFar = Math.max(currMax, maxSoFar);
        }
        return maxSoFar;

    }


    public static void main(String[] args) {
        int[] nums = {2, 4, 0, -4, 6, -8, 1};
        System.out.println(kandane(nums));

    }
}