五大常用算法
學(xué)習(xí)算法前,先了解一下五大常用算法,方便后續(xù)歸類總結(jié)及練習(xí),到達(dá)觸類旁通的效果。
一。分治算法:快速排序、歸并排序、大整數(shù)乘法、二分查找、遞歸(漢諾塔)
基本概念:把一個(gè)復(fù)雜的問題分成若干個(gè)相同或相似的子問題,再把子問題分成更小的子問題… , 知道最后子問題可以簡(jiǎn)單的直接求解,原問題的解即子問題的解的合并。
看上去有點(diǎn)類似Fork/Join框架,或map-reduce。
排序算法中的快速排序、歸并排序都是使用的分治算法。
分治算法的適用場(chǎng)景:
1)當(dāng)問題規(guī)模縮小到一定的程度就可以很容易解決
2)該問題可以分解為若干個(gè)規(guī)模較小的相同問題
3)該問題分解出的若干子問題的解可以合并為該問題的解
4)每個(gè)子問題都是獨(dú)立的,相互之間沒有交集。
使用分治法的經(jīng)典場(chǎng)景:
1)二分搜索
2)大整數(shù)乘法
3)合并排序
4)快速排序
5)漢諾塔
分治算法經(jīng)典例題:
輸入一組整數(shù),求出這組數(shù)字子序列和中最大值。也就是求出最大子序列的和,不必求出最大的那個(gè)序列。例如:序列:-2, 11, -1, 13, -5, -2 , 則最大子序列的和為20。
二。動(dòng)態(tài)規(guī)劃算法
基本概念:將待求解的問題分解為若干個(gè)子問題,按順序求解子問題,前一問題的解,為后一問題的求解提供有用的信息。在求解任一子問題時(shí),列出各種可能的局部解,通過(guò)決策保留那些有可能達(dá)到最優(yōu)的局部解,丟棄其他局部解。依次解決各種子問題,最后一個(gè)子問題就是初始問題的解。
由于動(dòng)態(tài)規(guī)劃算法解決的問題是有重疊的子問題,為了減少重復(fù)計(jì)算,對(duì)每一個(gè)子問題只解一次,將其不同階段的不同狀態(tài)保存在一個(gè)二維數(shù)組中。
動(dòng)態(tài)規(guī)劃算法以分治算法類似,不同在于:適合于動(dòng)態(tài)規(guī)劃算法求解的問題,經(jīng)分解后得到的子問題,往往不是互相獨(dú)立的,而是下一個(gè)子階段的求解是建立在上一個(gè)子階段的解的基礎(chǔ)上,進(jìn)行進(jìn)一步求解的。
動(dòng)態(tài)規(guī)劃的適用場(chǎng)景
1)最優(yōu)化原理:該問題的最優(yōu)解所包含的子問題的解也是最優(yōu)的。
2)無(wú)后效性:某階段狀態(tài)一旦確定,就不受這個(gè)狀態(tài)以后決策的影響。即某狀態(tài)以后的過(guò)程不會(huì)影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)。
3)有重疊子問題:即子問題之間不相互獨(dú)立,一個(gè)子問題的解在下一階段決策中可能被多次使用到。
經(jīng)典問題:
給定兩個(gè)字符串str1和str2,返回兩個(gè)字符串的最長(zhǎng)公共子序列,例如:str1=“1A2C3D4B56",str2=“B1D23CA45B6A”,"123456"和"12C4B6"都是最長(zhǎng)公共子序列,返回哪一個(gè)都行。
分析:這事經(jīng)典的動(dòng)態(tài)規(guī)劃問題,假設(shè)str1的長(zhǎng)度為M, str2的長(zhǎng)度為N, 則生成M*N的二維數(shù)組dp, dp[i][j]的含義是str1[0…i]與str2[0…j]的最長(zhǎng)公共子序列的長(zhǎng)度。
dp值的求法如下:
dp[i][j]的值比如和dp[i-1][j], dp[i][j-1]相關(guān),結(jié)合下面的代碼來(lái)看,實(shí)際上從第一行和第一列開始計(jì)算的,
三。貪心算法
貪心算法是通過(guò)局部最優(yōu)解來(lái)達(dá)到全局最優(yōu)解。
下面是一個(gè)可以試用貪心算法解的題目,貪心解的確不錯(cuò),可惜不是最優(yōu)解。
[背包問題]有一個(gè)背包,背包容量是M=150。有7個(gè)物品,物品可以分割成任意大小。
要求盡可能讓裝入背包中的物品總價(jià)值最大,但不能超過(guò)總?cè)萘俊?/p>
物品 A B C D E F G
重量 35 30 60 50 40 10 25
價(jià)值 10 40 30 50 35 40 30
分析:
目標(biāo)函數(shù): ∑pi最大
約束條件是裝入的物品總重量不超過(guò)背包容量,即∑wi<=M( M=150)
1)根據(jù)貪心的策略,每次挑選價(jià)值最大的物品裝入背包,得到的結(jié)果是否最優(yōu)呢?
2)每次挑選重量最小的物品裝入背包,是否能得到最優(yōu)解?
3)每次選取單位重量?jī)r(jià)值最大的物品,成為解本地的策略?
貪心算法簡(jiǎn)單易行,但貪心算法需要證明后才能真正運(yùn)用到算法中。一般來(lái)說(shuō),貪心算法的證明圍繞著整個(gè)問題的最優(yōu)解一定由在貪心策略中存在的子問題的最優(yōu)解得來(lái)的。
對(duì)于本題的三種貪心策略,都無(wú)法成立,即無(wú)法被證明。解釋如下:
1)選取價(jià)值最大者。
反例:W=30
物品:A B C
重量:28 12 12
價(jià)值:30 20 20
根據(jù)策略,選A, 但選BC最合適
2)選取重量最小,反例與上述類似
3)選取單位重量?jī)r(jià)值最大的物品。反例:
W=30
物品:A B C
重量:28 20 10
價(jià)值:28 20 10
根據(jù)策略,三種物品單位重量?jī)r(jià)值一樣,程序無(wú)法依據(jù)現(xiàn)有策略作出判斷,如果選擇A,則答案錯(cuò)誤。
2)貪心算法的經(jīng)典案例:
設(shè)有n個(gè)正整數(shù),將他們連成一排,組成一個(gè)最大的多位整數(shù)。
例如:n=3時(shí),3個(gè)整數(shù)13,312,343,連成的最大整數(shù)為34331213。
又如:n=4時(shí),4個(gè)整數(shù)7,13,4,246,連成的最大整數(shù)為7424613。
要求輸入:n, N個(gè)數(shù)
輸出:連成的多位數(shù)
算法分析:該題很容易想到貪心法,但解題時(shí)很多人把整數(shù)按從大到小的順序連接起來(lái),測(cè)試題目的例子也都符合,但結(jié)果不對(duì)。例如:我們很容易找到12, 121應(yīng)該組成12121而非12112, 但如12, 123呢,就是12312,而不是12123。所以,通過(guò)整數(shù)排序的方法是不對(duì)的。
結(jié)論:該題可以用貪心算法,只是剛才采用的貪心策略不對(duì)。正確的貪心算法的標(biāo)準(zhǔn)是:先把整數(shù)轉(zhuǎn)成字符串,然后再比較a+b和b+a, 如果a+b >= b+a, 就把a(bǔ)排在b前面, 反之把a(bǔ)排在b后面。
四。回溯算法
基本概念:回溯算法是一個(gè)類似枚舉的搜索嘗試過(guò)程,主要在搜索嘗試過(guò)程中尋找問題的解,當(dāng)發(fā)現(xiàn)已不滿足求解條件時(shí),就“回溯”返回,嘗試別的路徑。深度優(yōu)先。
回溯算法是一種選優(yōu)搜索法,按選優(yōu)條件向前搜索,以達(dá)到目標(biāo)。當(dāng)搜索到某一步時(shí),發(fā)現(xiàn)原先選擇并不優(yōu)或達(dá)不到目標(biāo),就退回一步重新選擇,這種走不通就退回再走的技術(shù)成為回溯法,而滿足回溯條件的某個(gè)狀態(tài)的點(diǎn)成為“回溯點(diǎn)”。
對(duì)于回溯算法的簡(jiǎn)單描述是:把問題的解空間轉(zhuǎn)化為圖或樹的結(jié)構(gòu),然后使用深度優(yōu)先進(jìn)行遍歷,遍歷過(guò)程中尋找所有可行解,從而找到最優(yōu)解。
其基本思想類似于:圖的深度優(yōu)先搜索;二叉樹的后序遍歷。
回溯法的詳細(xì)描述為:回溯法按深度優(yōu)先搜索解空間樹。首先從根節(jié)點(diǎn)出發(fā),當(dāng)搜索到解空間數(shù)的某一節(jié)點(diǎn)時(shí),先利用剪枝函數(shù)判斷該節(jié)點(diǎn)是否可行(即能得到問題的解)。如果不可行,則跳過(guò)對(duì)該節(jié)點(diǎn)為根的子樹的搜索,逐層向其祖先節(jié)點(diǎn)回溯;否則,進(jìn)入該子樹,繼續(xù)按深度優(yōu)先策略搜索。
2. 回溯算法的實(shí)現(xiàn):遞歸和迭代
回溯算法的經(jīng)典問題:0-1背包問題
有n種物品和一個(gè)背包,第i種物品的重量是wi,其價(jià)值為pi,背包的容量為c. 問:怎樣把物品裝入背包,背包中的物品的總價(jià)值最大。
分析:從n種物品中選擇部分物品,這樣的題目解空間是子集樹。例如,當(dāng)物品的種類數(shù)為3是,其解空間如下圖:
邊1表示選擇該物品,邊0表示不選擇該物品。這樣,這個(gè)樹從根節(jié)點(diǎn)到葉子節(jié)點(diǎn),包含了把物品放入背包的所有可能性。
回溯搜索過(guò)程,如果來(lái)到了葉子節(jié)點(diǎn),表示一條搜索路徑結(jié)束,如果該路徑上存在更優(yōu)的解,則保存下來(lái),如果不是葉子節(jié)點(diǎn),是中間的節(jié)點(diǎn)(如B), 就遍歷其子節(jié)點(diǎn)(D和E), 如果子節(jié)點(diǎn)滿足剪枝條件,就繼續(xù)回溯搜索子節(jié)點(diǎn)。
五。分支限界算法
基本概念
類似于回溯法,也是一種在問題的解空間樹T上搜索問題解的算法。但在一般情況下,分支限界法與回溯法的求解目標(biāo)不同。回溯法的求解目標(biāo)是找出解空間樹中滿足約束條件的所有解,而分支限界法的求解目標(biāo)則是滿足約束條件的一個(gè)解,或是從滿足約束條件的解中找出使某一目標(biāo)函數(shù)值達(dá)到極大或極小的解,即在某種意義下的最優(yōu)解。
分支限界法的基本思想是對(duì)有約束條件的最優(yōu)化問題的所有可行解(數(shù)目有限)空間進(jìn)行搜索。該算法在具體執(zhí)行時(shí),把全部可行的解空間不斷分割為越來(lái)越小的自己(成為分支),并為每個(gè)自己內(nèi)的解的值計(jì)算一個(gè)下界或上界(成為界定)。
在每次分支后,對(duì)凡是界限超出已知可行解值的那些子集不再做進(jìn)一步分支。這樣,解的許多子集(即搜索樹上的許多節(jié)點(diǎn))就可以不必考慮了,從而縮小了搜索范圍。這一過(guò)程一直進(jìn)行到找出可行解為止,該可行解的值不大于任務(wù)子集的界限,因此這種算法一般可以求得最優(yōu)解。
將問題分支為子問題,并對(duì)這些子問題定界的步驟稱為分支定界法。
知識(shí)附錄:深度優(yōu)先搜索和廣度優(yōu)先搜索
1)廣度優(yōu)先搜索:使用隊(duì)列的先進(jìn)先出
2)深度優(yōu)先搜索:
2. 分支限界法的經(jīng)典問題:旅行售貨員問題
1)問題描述:某售貨員要到若干城市去賣商品,已知各城市之間的路程。他要選定一條從駐地出發(fā),經(jīng)過(guò)每個(gè)城市一次,最后回到駐地的路線,使總的路程最小。
下圖為1,2,3,4 四個(gè)城市及路線圖,任意兩個(gè)城市之間不一定都有路可達(dá)。
2)問題理解:
分支限界法利用:廣度優(yōu)先搜索和最優(yōu)值策略
利用二位數(shù)組保存圖信息,一旦一個(gè)城市沒有通向另外城市的路,則不可能有回路,不用再找下去了。
我們?nèi)我膺x擇一個(gè)城市,作為出發(fā)點(diǎn)(因?yàn)樽詈蠖际且粋€(gè)回路,從哪出發(fā)都一樣)
3)關(guān)鍵思路:
想象一下,我們就是旅行員,從城市1出發(fā),根據(jù)廣度優(yōu)先搜索的思路,我們要把從城市1能到達(dá)的下一個(gè)城市,都要作為一種路徑走一下試試。可在程序里面怎樣實(shí)現(xiàn)這種“試試”呢?
答案是:可以利用一種數(shù)據(jù)結(jié)構(gòu),保存我們每走一步后,當(dāng)前的一些狀態(tài)參數(shù)。比如,我們已經(jīng)走過(guò)的城市數(shù)目(這樣就知道,我們有沒有走完,比如上圖,當(dāng)我們走了四個(gè)城市之后,無(wú)論從第四個(gè)城市是否能回到起點(diǎn)城市,都意味著我們走完了,只是這條路徑合不合約束以及能不能得到最優(yōu)解的問題)。我們把這種保存狀態(tài)參數(shù)的數(shù)據(jù)結(jié)構(gòu)定義成Node。需要另一個(gè)數(shù)據(jù)結(jié)構(gòu)用來(lái)保存我們每次試出來(lái)的路徑,這就是MiniHeap
Node{
int s; //結(jié)點(diǎn)深度,即當(dāng)前走過(guò)了幾個(gè)城市
int x[MAX_SIZE]; //保存走到這個(gè)結(jié)點(diǎn)時(shí)的路徑信息
}
MiniHeap{
//保存所有結(jié)點(diǎn)并提供一些結(jié)點(diǎn)的操作
}
————————————————
版權(quán)聲明:本文為CSDN博主「Shi Peng」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/shijinghan1126/article/details/87951372
總結(jié)
- 上一篇: 算法六——贪心
- 下一篇: 花花酱leetcode 题目——搜索专题