算法 --- 回溯法

回溯法

參考 - 劍指Offer

回溯法可以看成蠻力法的升級版,它從解決問題每一步的所有可能選項里系統地選擇出一個可行的解決方案.

回溯法解決的問題的特性:

  • 可以形象地用樹狀結構表示:

    • 節點: 算法中的每一個步驟
    • 節點之間的連接線: 每個步驟中的選項,通過每一天連接線,可以到達下一個子步驟
    • 葉子節點: 代表一個步驟的最終狀態
  • 如果在葉節點的狀態滿足需求,那么我們找到了一個可行的解決方案

  • 如果在葉節點的狀態不滿足約束條件,那么只好回溯到它的上一個節點再嘗試其他的選項。如果上一個節點所有可能的選項都已經試過,并且不能達到滿足約束條件的終結狀態,則再次回溯到上一個節點.如果所有節點的所有選項都已經嘗試過仍然不能達到滿足約束條件的終結狀態,該問題無解

栗子 - 數組總和

題目參考 - 39.數組總和

算法思路:

  • 變量:
    • 使用len緩存當前數組的長度
    • 使用path緩存當前的路徑
    • 使用res緩存要返回的結果
  • 處理:
    • 為了方便后續的剪枝操作,需先對數組進行排序
  • 使用深度優先算法,傳入3個參數: resides(離目標還差多少), path, begin(從哪一個開始添加)
    • 每次進入時,判斷一下,resides是否小于0:
      • 是: return
      • 否: 不做處理
    • 之后判斷resides是否等于0
      • 是: 證明找到一個條符合要求的路徑,將path推入res中(此處需特別注意,數組是JS中的引用類型.在后文中會回溯,最終的path是一個空數組. 如果直接將path推入res.其實是將path的內存地址推入res.最終會根據地址尋找到空數組.因此此處推入的是path.slice()). slice方法參考
      • 否: 不做處理
    • 到這里,循環遍歷candidates數組
      • 每次將當前的值推入路徑
      • 然后調用dfs函數
      • dfs函數結束之后,要進行回溯操作,即將對path使用pop()方法
var combinationSum = function(candidates, target){let len = candidates.length,path = [],res = []candidates.sort((a,b)=>a-b)function dfs(resides, path, begin){if(resides < 0) returnif(resides == 0) return res.push(path.slice())	// 此處需要返回一個新的數組,不能使用同一個內存中的數組for(let i = begin; i < len ; i++){if(resides - candidates[i] < 0) break;path.push(candidates[i])dfs(resides - candidates[i], path, i)path.pop()}}dfs(target, path, 0)return res       
}

注意: res.push(path)時,由于path是個引用類型.因此實際上push進的是一個十六進制地址.可以看做下面:

res[0] = ‘0xffffffff’

當后面回溯path.pop()時, 內存0xffffffff中的值會改變.

最后一次回溯 內存0xffffffff中的值為 []

因此 res[0] = []

而我們需要得到的是res[0] = [a,b,c] 這樣的結構。 因此我們每次在push時,需要重新生成一個數組傳入,即使用path.slice()

栗子 - 數組總和II

題目描述

算法思路:

以傳入參數combinationSum2([10, 1, 2, 7, 6, 1, 5], 8)為栗子進行說明:先將傳入的數組candidates進行升序排列, 即candidates = [1,1,2,5,6,7,10], 采用樹的深度優先遍歷.

  • resides: 離target =8 , 差多少
  • candicates: 當前的用于操作的候選數組
  • path: 當前的路徑
  • res: 最終返回的結構

當resides < 0時, 直接退出當前

當resides ===0 時,代表 path中的數組滿足條件. 將path推入res中 res.push(path.slice())

當resides > 0 時, 遍歷candidates數組:

  • 每次判斷 resides - candidates[i] 是否大于0 , 若小于0則進行剪枝(退出當前循環)

  • 同時要考慮[1,2, 5] 和 [1,7]的情況.因為原數組中有2個1, 只需第一個1即可. if(candidate[i] !== candidate[i-1])

  • 到這里就是正常的遞歸回溯工作了:

    • 每次將 candidates[i]推入path中.
    • 然后調用 dfs()遞歸
    • 出來回溯. path.pop()
var combinationSum2 = function(candidates, target) {candidates.sort((a, b) => a - b)var res = []function dfs(resides, candidates, path) {if (resides < 0) returnif (resides === 0) res.push(path.slice())for (let i = 0, len = candidates.length; i < len; i++) {if (candidates[i] !== candidates[i - 1]) {if (resides - candidates[i] < 0) breakpath.push(candidates[i])dfs(resides - candidates[i], candidates.slice(i + 1), path)path.pop()}}}dfs(target, candidates, [])return res
}

栗子 - 組合總和 III

題目參考

算法思路: 還是使用深度優先.

  • candidates:當前用于操作的數組
  • path: 當前的路徑
  • resides: 當前距離目標的差值

每次進入 dfs:

  • 首先檢查條件是否滿足:

    • resides若為負數,退出當前環境
    • path.length 若等于 k 則退出當前環境
    • candidates存在且candidates的長度為0,則退出當前環境
  • 然后循環candidates,對于每個candidates[i]

    • 得到當前的path = […path, candidates[i]]
    • 計算當前path長度,若等于k 則判斷 resides - candidates[i] 是否為0, 若為0,則將當前路徑推入res中。并退出
    • 遞歸調用 dfs(resides - candidates[i], candidates.slice(i+1), path)
    • 這里需要回溯 path.pop()
var combinationSum3 = function (k, n) {var res = []function dfs(candidates, resides, path) {if ((candidates && candidates.length == 0) || path.length > k || resides < 0) returnfor (let i = 0, len = candidates.length; i < len; i++) {path = [...path, candidates[i]]if (path.length === k && resides - candidates[i] == 0) return res.push(path.slice())dfs(candidates.slice(i + 1), resides - candidates[i], path)path.pop()}}dfs([1, 2, 3, 4, 5, 6, 7, 8, 9], n, [])return res
}

栗子 - 從根到葉子節點數字之和

題目參考

思路:

  • 使用 sum 保存總和, r 保存當前樹結構的根節點, path 保存當前的路徑(數組類型)
  • 使用dfs深度優先遍歷樹, 對于每次遍歷 dfs(root, path)
    • 判斷r 是否為空,若空則返回,否則執行下一步
    • 更新當前的path = […path, r.val]
    • 判斷當前是否為葉子節點:
      • 若是則: sum += path.join('') - 0. 其中-0是數字的隱式類型轉換
    • dfs(r.left, path)
    • dfs(r.rigth, path)
    • 回溯 path.pop()
var sumNumbers = function (root) {var sum = 0;function dfs(r, val) {if (!r) returnval = [...val, r.val]if (!r.left && !r.right) {return sum += val.join('') - 0}dfs(r.left, val)dfs(r.right, val)val.pop()}dfs(root, '')return sum
};

栗子 - 路徑總和II

題目參考

算法思路:大體的思路是深度優先遍歷,遍歷順序5 -> 4 -> 11 -> 7 --> 11 -> 2 --> 11 --> 4 -->5

其中,->代表下一個-->代表回退。遞歸循環調用dfs函數.傳入當前的樹結構的根節點r、距離總和差值resides和當前的路徑path

每次dfs循環如下:

  • 判斷r是否為null, 若是則返回
  • 生成當前的path.
  • 判斷 resides - r.val 是否為0
    • 若為0,則判斷當前是否是葉子節點
  • dfs 當前節點的左節點和右節點
var pathSum = function(root, sum){var res = []function dfs(resides, r, path){if(!r) returnpath = [...path, r.val]		// 這里使用[]隱式規則,在新的內存空間中生成了一個數組if(resides - r.val === 0 && !r.left && !r.right) return res.push(path)dfs(resides - r.val, r.left, path)dfs(resides - r.val, r.right, path)}dfs(sum, root, [])return res
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250256.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250256.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250256.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

013.Zabbix的Items(監控項)

一 Items簡介 Items是從主機里面獲取的所有數據&#xff0c;可以配置獲取監控數據的方式、取值的數據類型、獲取數值的間隔、歷史數據保存時間、趨勢數據保存時間、監控key的分組等。通常情況下item由key參數組成&#xff0c;如監控項中需要獲取cpu信息&#xff0c;則需要一個對…

Cookie 和 Session的區別

pass 下次再寫轉載于:https://www.cnblogs.com/nieliangcai/p/9073520.html

算法 --- 記一道面試dp算法題

題目: 給定一個數組(長度大于1),如下 let a [1,4,3,4,5] // 長度不確定,數值為整數要求寫一個函數,返回該數組中,除本身數字之外其他元素的成積.即返回如下: // 過程[4*3*4*5, 1*3*4*5, 1*4*4*5, 1*4*3*5, 1*4*3*4] // 結果[240, 60, 80, 60, 48]題目要求不使用除法,且時間…

編碼

一、什么是編碼&#xff1f;首先&#xff0c;我們從一段信息即消息說起&#xff0c;消息以人類可以理解、易懂的表示存在。我打算將這種表示稱為“明文”&#xff08;plain text&#xff09;。對于說英語的人&#xff0c;紙張上打印的或屏幕上顯示的英文單詞都算作明文。其次&a…

ASP.NET MVC 實現頁落網資源分享網站+充值管理+后臺管理(10)之素材管理

源碼下載地址&#xff1a;http://www.yealuo.com/Sccnn/Detail?KeyValuec891ffae-7441-4afb-9a75-c5fe000e3d1c 素材管理模塊也是我們這個項目的核心模塊&#xff0c;里面的增刪查改都跟文章管理模塊相同或者相似&#xff0c;唯一不同點可能是對附件的上傳處理&#xff0c;但…

javascript --- [express+ vue2.x + elementUI]登陸的流程梳理

說明 涉及到以下知識點: 登陸的具體流程express、vue2.x、elementUI、axios、jwt、assert 登陸方面的API使用中間件的使用前后端通過http狀態碼,進行響應的操作(這里主要是401)密碼驗證(bcrypt的hashSync方法對明文密碼進行加密,compareSync方法對加密的密碼進行驗證)token的…

設計模式---裝飾模式

今天學習了裝飾模式&#xff0c;做個筆記。。裝飾模式的基礎概念可以參考&#xff1a;https://blog.csdn.net/cjjky/article/details/7478788 這里&#xff0c;就舉個簡單例子 孫悟空有72變&#xff0c;但是它平時是猴子&#xff0c;遇到情況下&#xff0c;它可以變成蝴蝶等等 …

springMvc 注解@JsonFormat 日期格式化

1&#xff1a;一定要加入依賴,否則不生效&#xff1a; <!--日期格式化依賴--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version>&…

Git很簡單--圖解攻略

Git Git 是目前世界上最先進的分布式版本控制系統&#xff08;沒有之一&#xff09;作用 源代碼管理為什么要進行源代碼管理? 方便多人協同開發方便版本控制Git管理源代碼特點 1.Git是分布式管理.服務器和客戶端都有版本控制能力,都能進行代碼的提交、合并、. 2.Git會在根…

css --- 使用scss生成常用的基本css樣式

"工具樣式"的概念和 SASS(SCSS) 在webpack中使用sass 安裝sass和sass-loader $ npm i sass sass-loader由于使用了腳手架,安裝完畢后重啟前端即可 樣式重置 其實就是樣式的初始化 // reset* {box-sizing: border-box; // 以邊框為準. css3盒模型outline: none;…

vc/vs開發的應用程序添加dump崩潰日志轉

原貼地址&#xff1a;https://blog.csdn.net/wangkui1331/article/details/78029940 vc/vs開發的應用程序出現崩潰的時候&#xff0c;由于沒有任何記錄&#xff0c;導致開發人員很難追蹤&#xff0c;但是添加dump文件后&#xff0c;就可以免除這些煩惱 1.添加方法 &#xff08;…

51 nod 1127最短的包含字符串(尺取法)

1127 最短的包含字符串 收藏關注給出一個字符串&#xff0c;求該字符串的一個子串S&#xff0c;S包含A-Z中的全部字母&#xff0c;并且S是所有符合條件的子串中最短的&#xff0c;輸出S的長度。如果給出的字符串中并不包括A-Z中的全部字母&#xff0c;則輸出No Solution。Input…

Java --- 基礎學習Ⅰ

第一章 開發前言 位、字節 位(bit): 一個數字0或一個數字1,代表一位 字節(Byte): 每逢8位是一個字節,這時數據存儲的最小單位 1 Byte 8 bit 1 KB 1024 Byte 1 MB 1024 KB 1 GB 1024 MB 1 TB 1024 GB 1 PB 1024 TB MS-DOS(Microsoft Disk Operating System) 第二章 Ja…

JSON 數據重復 出現$ref

JSONArray 類型 如果我們往里面add數據的時候 如果數據相同&#xff0c;那么就會被替換成 $ref: 也就是被簡化了 因為數據一樣所直接 指向上一條數據 循環引用&#xff1a;當一個對象包含另一個對象時&#xff0c;fastjson就會把該對象解析成引用。引用是通過$ref標示的&am…

Java --- 基礎學習Ⅱ

繼承 繼承概述 下面有一個學生類 public class Student{private String name;private int age;public void study(){System.out.println("努力學習了");}public String getName() {return name;}public void setName(String name) {this.name name;}public int g…

urllib庫

python內置的最基本的HTTP請求庫&#xff0c;有以下四個模塊&#xff1a; urllib.request  請求模塊 urllib.error    異常處理模塊 urllib.parse   url解析模塊 urllib.robotparser robots.txt解析模塊 urllib.request請求模塊&#xff1a; urllib.request.urlopen(u…

layer的刪除詢問框的使用

刪除是個很需要謹慎的操作 我們需要進行確認 對了刪除一般使用ajax操作 因為如果同url請求 處理 再返回 會有空白頁 1.js自帶的樣式 <button type"button" data-toggle"tooltip" title"刪除" class"btn btn-danger pull-right btn-xs&qu…

文獻筆記(八)

一、基本信息 標題&#xff1a;MySQL數據庫在自動測試系統中的應用 時間&#xff1a;2017 出版源&#xff1a;寧夏職業技術學院 領域分類&#xff1a;無線互聯科技 二、研究背景 問題定義&#xff1a;文章介紹了MySQL數據庫的特點&#xff0c;結合自動測試系統運行中的實際&…

Java --- 常用API

常用API 方法重載: 方法名相同,方法接收的參數不同 static: 修飾的類,可以直接使用類名進行調用 方法名說明public static abs(int a)返回參數的絕對值public static double ceil(double a)返回大于或等于public static double floor(double a)返回小于或等于參數的最大doubl…

9. 彈出鍵盤擋住input

1.) react 中 <input className"inp3" placeholder"密碼" type"password" onChange{this.changepassword.bind(this)} onFocus{this.FocusFN.bind(this)} value{this.state.paswword}/> FocusFN(){ setTimeout(()>{ let pannel docume…