欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言動態(tài)規(guī)劃點(diǎn)殺dp算法LeetCode炒股習(xí)題案例解析

 更新時間:2022年02月14日 14:16:25   作者:喬喬家的龍龍  
這篇文章主要介紹為了C語言動態(tài)規(guī)劃點(diǎn)殺dp算法,本文以LeetCode炒股習(xí)題案例來為大家進(jìn)行詳細(xì)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助

概念

說到動態(tài)規(guī)劃,什么是動態(tài)規(guī)劃?

動態(tài)規(guī)劃(英語:Dynamic programming,簡稱 dp)通過把原問題分解為相對簡單的子問題的方式求解復(fù)雜問題的方法。動態(tài)規(guī)劃常常適用于有重疊子問題和最優(yōu)子結(jié)構(gòu)性質(zhì)的問題。

看著這么復(fù)雜哈,其實(shí)總結(jié)出來就是大事化小,拆分成小問題但是這些小問題和原問題是同質(zhì)的,動規(guī)致力于解決每一個子問題,減少計(jì)算,其實(shí)和遞歸思想,分治法有些類似,斐波那契數(shù)列就可以看做入門級的經(jīng)典動規(guī)問題

這里引用一個網(wǎng)上流行的例子來給大家體會一下:

A :“1+1+1+1+1+1+1+1 =?”
A :“上面等式的值是多少”
B :計(jì)算 “8”
A : 在上面等式的左邊寫上 “1+” 呢?
A : “此時等式的值為多少”
B : 很快得出答案 “9”
A : “你怎么這么快就知道答案了”
A : “只要在8的基礎(chǔ)上加1就行了”
A : “所以你不用重新計(jì)算,因?yàn)槟阌涀×说谝粋€等式的值為8!動態(tài)規(guī)劃算法也可以說是 ‘記住求過的解來節(jié)省時間’”

性質(zhì)

1.最優(yōu)化原理:如果問題的最優(yōu)解所包含的子問題的解也是最優(yōu)的,就稱該問題具有最優(yōu)子結(jié)構(gòu),即滿足最優(yōu)化原理(說人話就是切大瓜,切到最小又不影響我體驗(yàn))

2.有重疊子問題:即子問題之間是不獨(dú)立的,一個子問題在下一階段決策中可能被多次使用到(說人話就是藕斷絲連,拿一個可能帶動其他)

3.無后效性:即某階段狀態(tài)一旦確定,就不受這個狀態(tài)以后決策的影響。也就是說,某狀態(tài)以后的過程不會影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)(說人話就是把水化成冰,但本質(zhì)上依然是水)

典型特征

動態(tài)規(guī)劃有4個典型特征:

1.最優(yōu)子結(jié)構(gòu)

2.狀態(tài)轉(zhuǎn)移方程

3.邊界

4.重疊子問題

以我們熟悉的斐波那契數(shù)列為例

在這里插入圖片描述

f(n-1)和f(n-2) 稱為 f(n) 的最優(yōu)子結(jié)構(gòu),f(n)= f(n-1)+f(n-2)就稱為狀態(tài)轉(zhuǎn)移方程,f(1) = 1, f(2) = 2 稱為邊界,其中f(5)= f(4)+f(3),f(4) = f(3) + f(2) ,f(3)就是重疊子問題。

實(shí)戰(zhàn)論證

要學(xué)習(xí)dp算法就一定得談?wù)?LeetCode 里面的鼻祖題——炒股系列問題,我們就拿例題來港港怎么理解他的典型特征

初始題比較簡單,我們以 II 為例:

在這里插入圖片描述

示例:
輸入: prices = [7,1,5,3,6,4]
輸出: 7

小捷徑

看到這里其實(shí)最簡單的方法已經(jīng)明了了,那就是貪心算法,只要能賺,只要不賠我就買買買!你說我貪不貪心?

int maxProfit(int* prices, int pricesSize) {
    int sum = 0;
    for (int i = 1; i < pricesSize; ++i) {
        sum += fmax(0, prices[i] - prices[i - 1]);
    }
    return sum;
}

這里用了一個庫函數(shù) fmax ,需要引頭文件<math.h>,用于比較兩個參數(shù)的最大值,語法是:

type fmax  (參數(shù)1 , 參數(shù)2);

再介紹一種我自己用的方法,和貪心原理上差不多,只是用的普普通通的遍歷:

int maxProfit(int* prices, int pricesSize) {
	int n = 0;
	if (pricesSize == 0)
	{
		return 0;
	}
	int sum = 0;
	while (n < pricesSize - 1)
	{
		for (n = 0; n < pricesSize - 1; n++)
			if (prices[n + 1] - prices[n] > 0)//保證買賣能賺就入手
			{
				sum += prices[n+1]-prices[n];
			}
	}
	return sum;
}

我自己的方法還是比較優(yōu)的

在這里插入圖片描述


這樣就能一套帶走,但我們要用 dp 去搞定他,dp 其實(shí)也很簡單,只是看著有點(diǎn)復(fù)雜,咱不能望而卻步是吧。

分析條件,題目中說不能多次買賣,那我們有且只有兩種狀態(tài)就是沒有和有一支,沒有就是手里為0,又有兩種可能就是前一天就是 0 和這一天有一支但被賣出去了;同理,有一支的情況就是前一天就有一支和前一天兩手空空但我今天買進(jìn)了一支。以此我們寫出求最大利潤的狀態(tài)轉(zhuǎn)移方程( i 從 0 開始):

第i天有0支股票:dp[i][0] = dp[i-1][0] + dp[i][1]+prices[i];
第i天有1支股票:dp[i][1] = dp[i-1][1] + dp[i-1][0]-prices[i];

狀態(tài)轉(zhuǎn)移方程寫出來了,題目就迎刃而解了

算法實(shí)現(xiàn)

1、借助數(shù)組或者二維數(shù)組,保存每一個子問題的結(jié)果,具體創(chuàng)建數(shù)組還是二維數(shù)組看題目而定,比如找零錢問題中的不同面值零錢與總錢數(shù),這樣就需要創(chuàng)建一個二維數(shù)組

2、對應(yīng)題干條件,具體要求來設(shè)置數(shù)組邊界值,一維數(shù)組就是設(shè)置第一個數(shù)字,二維數(shù)組就是設(shè)置第一行跟第一列的值

3、找出狀態(tài)轉(zhuǎn)換方程,找到每個狀態(tài)跟他上一個狀態(tài)的關(guān)系,根據(jù)狀態(tài)轉(zhuǎn)化方程就可以寫出代碼

我們用剛剛推出來的狀態(tài)轉(zhuǎn)移方程就可以寫出整個代碼框架:

int maxProfit(int* prices, int pricesSize) {
    int sz = pricesSize;
    int i = 0;
    int dp[sz][2] = 0; //sz是最大買賣天數(shù)內(nèi)的價(jià)格,2代表兩種狀態(tài)0和1
    dp[0][0] = 0,dp[0][1]=-prices[0];//設(shè)置邊界值
    for(i=0;i<sz;i++)
    {
    dp[i][0] = fmax(dp[i-1][0] + dp[i][1]+prices[i]);
    dp[i][1] = fmax(dp[i-1][1] + dp[i-1][0]-prices[i]);//兩種狀態(tài)分別求最大利潤
    }
    return [sz-1][0];
  }

優(yōu)化

我們不難發(fā)現(xiàn),我們的收益只和股票前一天的價(jià)格掛鉤,和更早的狀態(tài)沒有關(guān)系,那我們?yōu)榱藴p小時間復(fù)雜度和空間復(fù)雜度,可以將二維數(shù)組轉(zhuǎn)化成一維滾動數(shù)組搞定

int maxProfit(int* prices, int pricesSize) {
    int dp[pricesSize][2];
    int dp0 = 0;dp1 = -prices[0];
    for (int i = 1; i < pricesSize; ++i)
     {
       int Dp0 = fmax(dp0, dp1+prices[i]);
        Dp1 = fmax(dp1, dp0-prices[i]); //同理轉(zhuǎn)換出狀態(tài)轉(zhuǎn)移方程
    }
    dp0 = Dp0;
    dp1 = Dp1;//滾動更新dp0和dp1
    return dp[pricesSize - 1][0];
}

好了,今天就先到這里,摸了家人們,更多關(guān)于C語言動態(tài)規(guī)劃點(diǎn)殺dp算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • strcat 函數(shù)的使用指南

    strcat 函數(shù)的使用指南

    strcat是連接字符串的函數(shù)。函數(shù)返回指針,兩個參數(shù)都是指針,第一個參數(shù)所指向的內(nèi)存的地址必須能容納兩個字符串連接后的大小。
    2015-09-09
  • C++利用Socket實(shí)現(xiàn)主機(jī)間的UDP/TCP通信

    C++利用Socket實(shí)現(xiàn)主機(jī)間的UDP/TCP通信

    這篇文章主要為大家詳細(xì)介紹了C++如何利用Socket實(shí)現(xiàn)主機(jī)間的UDP/TCP通信功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-01-01
  • C++面試題之?dāng)?shù)a、b的值互換(不使用中間變量)

    C++面試題之?dāng)?shù)a、b的值互換(不使用中間變量)

    這篇文章主要介紹了不使用中間變量,C++實(shí)現(xiàn)數(shù)a、b的值互相轉(zhuǎn)換操作,感興趣的小伙伴們可以參考一下
    2016-07-07
  • c++ 編程 幾個有用的宏詳解

    c++ 編程 幾個有用的宏詳解

    下面小編就為大家?guī)硪黄猚++ 編程 幾個有用的宏詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • 解決Devc++運(yùn)行窗口中文亂碼的實(shí)現(xiàn)步驟

    解決Devc++運(yùn)行窗口中文亂碼的實(shí)現(xiàn)步驟

    本文主要介紹了如何解決Devc++運(yùn)行窗口中文亂碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • C語言線性代數(shù)算法實(shí)現(xiàn)矩陣示例代碼

    C語言線性代數(shù)算法實(shí)現(xiàn)矩陣示例代碼

    這篇文章主要為大家介紹了使用C語言線性代數(shù)的算法來實(shí)現(xiàn)矩陣示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • Qt 實(shí)現(xiàn)畫線筆鋒效果詳細(xì)原理及示例代碼

    Qt 實(shí)現(xiàn)畫線筆鋒效果詳細(xì)原理及示例代碼

    這篇文章主要介紹了Qt 實(shí)現(xiàn)畫線筆鋒效果詳細(xì)原理及示例代碼。文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    堆是計(jì)算機(jī)科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個可以被看做一棵完全二叉樹的數(shù)組對象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。本文將通過圖片詳細(xì)介紹堆排序,需要的可以參考一下
    2022-06-06
  • C語言創(chuàng)建鏈表錯誤之通過指針參數(shù)申請動態(tài)內(nèi)存實(shí)例分析

    C語言創(chuàng)建鏈表錯誤之通過指針參數(shù)申請動態(tài)內(nèi)存實(shí)例分析

    這篇文章主要介紹了C語言創(chuàng)建鏈表錯誤之通過指針參數(shù)申請動態(tài)內(nèi)存,是鏈表創(chuàng)建過程中非常常見的經(jīng)典錯誤。實(shí)例中做了較為詳盡的分析,需要的朋友可以參考下
    2014-09-09
  • C++ 中友元函數(shù)與友元類詳解

    C++ 中友元函數(shù)與友元類詳解

    這篇文章主要介紹了C++ 中友元函數(shù)與友元類詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評論