演算法基礎 - 列舉/遞迴/動歸/深廣搜/二分/貪心
列舉
概念
- 基於已有知識進行答案猜測的求解策略
- 對解集合中的每一項根據條件進行檢驗
- 不重複檢驗
- 很多情況下列舉意味著使用迴圈
- 一般性 + 完備性
分析
原子 - 區域性 - 整體
- 拆分出原子操作,分析每個原子操作的影響、規律
- 確定列舉物件、範圍和判定條件
- 逐一列舉可能的解並驗證是否是問題的解
- 關鍵問題
- 給出解空間,建立簡潔的數學模型,減少列舉的狀態數目
- 減少搜尋空間,縮小各變數取值範圍,避免不必要的計算
- 合適的搜尋順序,簡化過程,及早排除明確的錯誤答案
技巧
- 如果存在某個區域性,一旦區域性的狀態被確定,剩餘部分的狀態只能是確定的一種或較少種,那麼只需列舉區域性狀態。固定部分,確定規律
- 儘可選使用stl演算法和合適的資料結構來縮減時間
- 好的排序和處理順序非常重要
遞迴
概念
- 函式直接或間接的呼叫自身
- 與列舉的比較
- 列舉的子問題之間是平行的、沒有相互依存關係的,遞迴的子問題是縱向依存的
分析
- 能劃分成相同性質的子問題,通常體現為自相似性
- 關鍵
- 遞迴式:如何劃分成子問題
- 遞迴出口:如何確定最小子問題
- 界函式:如何保證規模縮減
技巧
- 遞迴函式使用狀態變數引數記錄狀態變化過程,當拆分出的子問題不具備自相似性時,可以通過增加狀態引數來增加限制
- 使用狀態表維護狀態
- 遞迴容易發生大量重複計算,使用記錄表避免重複計算
- 用棧代替遞迴以提高效率
- 遞迴轉化成遞推(自頂向下轉換成自底向上)
- 遞迴轉化為動態規劃
動態規劃
性質
- 最優子結構,問題最優解包含的子問題的解也是最優的。(最優不一定是明顯的,可能只能在相鄰一層的子問題中體現)
- 無後效性。當某些狀態值確定後,此後所需求出的狀態值就只和這些狀態有關,而與此前通過何種路徑經過何種狀態無關
- 人人為我/我為人人遞推型動態規劃
分析
- 將原問題分解為子問題
- 子問題與原問題形式相同或類似,但規模更小
- 子問題求出的解要記錄,保證每個子問題只求解一次
- 確定狀態
- 和子問題相關的各個變數的一組取值是一個狀態
- 確定初始/邊界狀態的值
- 即填充狀態陣列的部分內容
- 確定狀態轉移方程
- 如何從已知的狀態求出另一狀態,即利用狀態陣列已有內容計算需要填充的其他內容
- 類似於遞迴
技巧
- 每次只拆除單獨一個操作單位,來尋找狀態轉移方程
- 若無明顯確定的初始狀態,可全部初始化為某個一般值,並按照某種排序順序進行遞遍歷更新
- 若無法形成遞推關係,則考慮細化引數列表,增加限制條件
深度&廣度優先搜尋
比較
- 廣搜一定能獲得最優解,但具有盲目性,在搜尋過程中需要大量儲存空間,適合用queue
- 深搜需要優化搜尋範圍,但搜尋過程需要的空間較小,適合用stack
技巧
- 使用廣搜時,在將節點加入佇列前,可以通過對全域性陣列狀態表(Open/Closed)進行更新或是在結構型別中設定其父指標的方式,在搜尋結束後還原解的路徑
- 雙向廣度優先搜尋能明顯減少搜尋樹的寬度
二分查詢
- 前提:已排序的序列
技巧
- 最小值問題 》判定性問題(二分判定在某個值時能否滿足條件)
貪心演算法
- 求解時,做出僅當前最好的選擇
- 不能保證全域性最優
- 關鍵是貪心策略的選擇
- 自頂向下分解為子問題
- 具有無後效性
分析
- 建立數學模型
- 分解成子問題
- 對每一子問題求得區域性最優解
- 合併子問題
其他技巧
設定冗餘陣列
- 通過填充冗餘陣列,減少邊界判斷程式碼
- 是以空間換時間的方式,通常是利大於弊的
使用一個自增變數進行序列列舉
- 通過迴圈自增變數,獲取各個位的01情況來獲得一個全部情況列舉
- 或者維護一個陣列,在每次自增時判斷是否需要進位
壓縮多個01狀態至單個變數
- 使用一個變數的各個位分別表示每個狀態,使用時用
&
按位與運算分別與1/2/4/8…計算後與0比較進行判斷
剪枝
- 型別
- 最優化剪枝(先考慮,大多與演算法整體處理思路/順序有關)
- 可行性剪枝(後考慮,大多與處理過程中的區域性判斷有關)
- 優先進行列舉數量少的步驟進行嘗試和排除
- 避免計算機會出現(人能輕易規避)的無效重複
- 具體問題具體分析,發掘有效剪枝方式
字典序存取
- 即給定排列求序號/給定序號求排列
- 採用從頭按位固定計算排列總數的方法逐位推導
- 是否按有效序列壓縮/時間空間權衡
- 狀態數較小時,直接方式編碼,以空間換時間
- 狀態數較多/採用直接方式會導致大量空間被無效狀態消耗時,用字典序(其他編碼方式),以時間換空間
相關文章
- 演算法基礎–貪心策略演算法
- 二分與貪心-Gone Fishing(演算法基礎 第9周)Go演算法
- [Coursera]演算法基礎_Week8_二分與貪心_Q1演算法
- [Coursera]演算法基礎_Week8_二分與貪心_Q3演算法
- [Coursera]演算法基礎_Week8_二分與貪心_Q2演算法
- 2017廣東工業大學程式設計競賽決賽 題解&原始碼(A,數學解方程,B,貪心博弈,C,遞迴,D,水,E,貪心,面試題,F,貪心,列舉,LCA,G,dp,記憶化搜尋,H,思維題)...程式設計原始碼遞迴面試題
- 淺談貪心與動歸
- 演算法基礎--遞迴和動態規劃演算法遞迴動態規劃
- CF448C Painting Fence(遞迴+貪心)AI遞迴
- 遞迴實現指數型列舉遞迴
- POJ 2718簡單列舉貪心演算法(好久沒寫程式碼了。。)演算法
- Swift遞迴列舉與紅黑樹Swift遞迴
- 0基礎演算法基礎學演算法 第六彈 遞迴演算法遞迴
- 求最大子陣列(貪心演算法)陣列演算法
- 馬踏棋盤演算法(騎士周遊問題)----遞迴與貪心優化演算法演算法遞迴優化
- HDU 5303 Delicious Apples (貪心 列舉 好題)APP
- 【演算法拾遺】二分查詢遞迴非遞迴實現演算法遞迴
- Java基礎--列舉Java
- 【java基礎】列舉Java
- 貪心演算法演算法
- 迴歸Java基礎:LinkedBlockingQueue阻塞佇列解析JavaBloC佇列
- 【基礎演算法】(07)五大常用演算法之三:貪心演算法演算法
- java基礎:enum列舉Java
- 【java基礎】--Java列舉Java
- 資料結構與演算法——歸併排序: 陣列&連結串列&遞迴&非遞迴解法全家桶資料結構演算法排序陣列遞迴
- 貪心演算法(貪婪演算法,greedy algorithm)演算法Go
- Luogu P4425 轉盤 題解 [ 黑 ] [ 線段樹 ] [ 貪心 ] [ 遞迴 ]遞迴
- 演算法---貪心演算法和動態規劃演算法動態規劃
- 學一下貪心演算法-學一下貪心演算法演算法
- ?Java基礎之Java列舉Java
- JavaSE基礎:列舉型別Java型別
- Python基礎之棧與佇列及遞迴目錄Python佇列遞迴
- 貪心演算法Dijkstra演算法
- 9-貪心演算法演算法
- Python遞迴函式,二分查詢演算法Python遞迴函式演算法
- 分類演算法-邏輯迴歸與二分類演算法邏輯迴歸
- 前端基礎迴歸-URI和URL前端
- 線性迴歸基礎程式碼