力扣刷題筆記(11)

開始做動態規劃部分的內容了,這部分有四個題,所以就對半開吧。

做這些題目的時候,有那麼一些感覺像是回到了小時候做奧數的感覺,反正都是難。

第一題:(爬樓梯)

假設你正在爬樓梯。需要 n 階你才能到達樓頂。

每次你可以爬 12 個臺階。你有多少種不同的方法可以爬到樓頂呢?

注意:給定 n 是一個正整數。

示例 1:

輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1.  1+ 12.  2 階
示例 2:

輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1.  1+ 1+ 12.  1+ 23.  2+ 1> 來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/climbing-stairs
> 著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。


第二題:買賣股票的最佳時機

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

如果你最多隻允許完成一筆交易(即買入和賣出一支股票一次),設計一個算法來計算你所能獲取的最大利潤。

注意:你不能在買入股票前賣出股票。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 5

解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
注意利潤不能是 7-1 = 6, 因爲賣出價格需要大於買入價格;同時,你不能在買入前賣出股票。
示例 2:

輸入: [7,6,4,3,1]
輸出: 0

解釋: 在這種情況下, 沒有交易完成, 所以最大利潤爲 0。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。


我的題解(1)

這題居然判定爲簡單題,看來是我太菜了。

我倒也不是做不出來,只是我的算法無法處理過大的數據,哎。

我是這樣想的:既然有n個臺階,假設兩步走的次數爲k,則一步走的次數就是n-2k,那麼將這些兩步走的次數穿插在一步走的情況當中,就是一個排列組合問題。

那就將排列組合整理成一個函數,對k進行遞歸併求和2,便是最後的結果。

於是代碼就出來了:


//二代版本
int twostep(int n,int two)
{
	int temp = 1;
	int i = n - two;
	int del = 1;

	for (; i > n - 2 * two; i--)
	{
		temp *= i;
		while (temp % del == 0 && del <= two)
		{
			temp /= del;
			del++;
		}
	}
	while (del <= two)
	{
		temp /= del;
		del++;
	}
	return temp;
}

int climbStairs(int n) 
{
	int step = n / 2;
	int ret = 1;
	while (step > 0)
	{
		ret += twostep(n, step);
		step--;
	}
	return ret;
}

一代版本是全乘完再統一除。

然後發現當n到35的時候就扛不住了,換了二代版本。沒想到還是抗不過45。
其實如果將除數放在數組裏面做三代版本是可以的,但是那樣就太肥了。。。

最後,我接受了現實,人外有人,那就看看別人怎麼做的。
斐波那契數列。。。

斐波那契解法
int climbStairs(int n) {
        if(n==1||n==2)
            return n;
        int n1=1,n2=2;
        for(int i=3;i<=n;i++)
            {
            int temp=n1+n2;
            n1=n2;
            n2=temp;
        }
        return n2;
    }

原來這是一個找規律的題目啊。。。


我的題解(2)

上次做的那題,可以多次買賣,這次只能單次,那波峯波谷法就不好用了。

因爲當天下降可能是“虛假下降”,接下來會有反彈。

其實虛假下降也好判斷。但是吧,困擾我的是:

“過度虛假下降”:就是後面會反彈,但是這個下降力度已經超過了之前積攢下來的盈利,出現這種情況,應該認爲之前的天數都不存在,從波谷重頭來過。

其實這個情況單獨處理也並不是什麼很難的事情,但是把這些單獨處理都沒什麼問題的糅雜在一起的時候,那就很麻煩了。


前面失敗了之後,我又想起了最初那個被掐斷的小火苗:乾脆遞歸傳入當前最小值,遍歷找利益最大處。然後,過了。

int maxProfit(vector<int>& prices) {
        if (prices.size() < 1)
            return 0;
        int the_min= prices[0];
        int ret = 0;

        for (int i = 1; i < prices.size(); i++) {
            ret = max(ret, prices[i] - the_min);
            the_min = min(the_min, prices[i]);
        }
        return ret;
    }

其實我只是嘗試一下,因爲一開始掐滅這個想法也不是沒有道理的。
因爲最後買入點可不一定會是波谷,賣出點是不是波峯倒是無所謂,關鍵就是那個買入點。

但是,當它奇蹟般的通過的時候,我突然想通了,ret和不止有the_min一個變量在控制,所以the_min是不是波谷對ret並沒有絕對的影響。

有點繞,沒繞出來打盤王者冷靜冷靜。一定是可以繞出來的。


官方題解(1)

方法三:動態規劃(斐波那契數列)
算法

不難發現,這個問題可以被分解爲一些包含最優子結構的子問題,即它的最優解可以從其子問題的最優解來有效地構建,我們可以使用動態規劃來解決這一問題。

第 ii 階可以由以下兩種方法得到:

在第 (i-1) 階後向上爬一階。

在第 (i−2) 階後向上爬 2 階。

所以到達第 ii 階的方法總數就是到第 (i-1)(i−1) 階和第 (i-2)(i−2) 階的方法數之和。

令 dp[i]dp[i] 表示能到達第 ii 階的方法總數:

dp[i]=dp[i-1]+dp[i-2]
dp[i]=dp[i−1]+dp[i−2]

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode/
來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。


官方題解(2)

方法二:一次遍歷
算法

假設給定的數組爲:[7, 1, 5, 3, 6, 4]

如果我們在圖表上繪製給定數組中的數字,我們將會得到:

在這裏插入圖片描述

我們來假設自己來購買股票。隨着時間的推移,每天我們都可以選擇出售股票與否。那麼,假設在第 i 天,如果我們要在今天賣股票,那麼我們能賺多少錢呢?

顯然,如果我們真的在買賣股票,我們肯定會想:如果我是在歷史最低點買的股票就好了!太好了,在題目中,我們只要用一個變量記錄一個歷史最低價格 minprice,我們就可以假設自己的股票是在那天買的。那麼我們在第 i 天賣出股票能得到的利潤就是 prices[i] - minprice。

因此,我們只需要遍歷價格數組一遍,記錄歷史最低點,然後在每一天考慮這麼一個問題:如果我是在歷史最低點買進的,那麼我今天賣出能賺多少錢?當考慮完所有天數之時,我們就得到了最好的答案。

作者:LeetCode-Solution
鏈接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/
來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

public class Solution {
    public int maxProfit(int prices[]) {
        int minprice = Integer.MAX_VALUE;
        int maxprofit = 0;
        for (int i = 0; i < prices.length; i++) {
            if (prices[i] < minprice)
                minprice = prices[i];
            else if (prices[i] - minprice > maxprofit)
                maxprofit = prices[i] - minprice;
        }
        return maxprofit;
    }
}

> 作者:LeetCode-Solution
> 鏈接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/
> 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

總結

動手前,還是先想清楚吧。。。。。。
永遠不要節省整理思緒的時間,不然,在實現功能的時候都會讓你還。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章