搜索回溯算法(DFS)1------遞歸

目錄

簡介:

遞歸問題解題的思路模板

例題1:漢諾塔

例題2:合并兩個有序鏈表

例題3:反轉鏈表

例題4:兩兩交換鏈表中的節點

例題5:Pow(x,n)-快速冪

結語:


簡介:

本系列將會帶大家深入理解搜索中的一大分支深搜,深搜是離不開遞歸的和回溯思想的(優化需要剪枝),故我會在例題中詳細指出解決這一系列問題的思考思路和解題技巧。

那么我們就從遞歸開始(深搜的基礎)也就是本文中主要介紹的。

什么是遞歸?

簡單來說就是函數自己調用自己。

為什么會用到遞歸?

大問題可以拆解成相同的子問題,且子問題的解法和大問題的一模一樣,這是就可以用到遞歸。

在解決?個規模為n的問題時,如果滿?以下條件,我們可以使用遞歸來解決:

a. 問題可以被劃分為規模更?的?問題,并且這些?問題具有與原問題相同的解決?法。

b. 當我們知道規模更?的?問題(規模為n-1)的解時,我們可以直接計算出規模為n的問題的解。

c. 存在?種簡單情況,或者說當問題的規模?夠?時,我們可以直接求解問題。

?般的遞歸求解過程如下:

a. 驗證是否滿?簡單情況。

b. 假設較?規模的問題已經解決,解決當前問題。

上述步驟可以通過數學歸納法來證明。

如何理解遞歸?

不要太在意細節,相信函數。?

遞歸問題解題的思路模板

當然在設計遞歸函數之前最重要的是你要你的遞歸函數干嘛。

1.遞歸函數的作用

2.相同子問題------------函數頭

3.只關心某一個子問題是如何解決的------------函數體

4.遞歸出口

建議友友在寫遞歸類型的題目是一定要把這三個地方考慮清楚了再下手。

最后就是相信函數。

例題1:漢諾塔

鏈接:漢諾塔

題目簡介:

遞歸問題非常經典的一道題目,在經典漢諾塔問題中,有 3 根柱子及 N 個不同大小的穿孔圓盤,盤子可以滑入任意一根柱子。一開始,所有盤子自上而下按升序依次套在第一根柱子上(即每一個盤子只能放在更大的盤子上面)。移動圓盤時受到以下限制:
(1) 每次只能移動一個盤子;
(2) 盤子只能從柱子頂端滑出移到下一根柱子;
(3) 盤子只能疊在比它大的盤子上。

請編寫程序,用棧將所有盤子從第一根柱子移到最后一根柱子。

解法:

我們可以看到每次都可以把大問題分解成相同的子問題,且子問題的解決方法和大問題的一模一樣故我們可以使用遞歸來處理。?

1.遞歸函數的作用

函數作?:將A中的上?n個盤?挪到C中。這里的A和C是函數參數的A和C不是實際的(很重要)。

2.相同子問題(函數頭)

我們要設計一個函數頭來完成漢諾塔的遞歸過程,我們可以看到我們需要三根柱子和要記錄下來還剩下幾個盤子。故我們的函數頭可以設計成public void dfs(List<Integer>?a, List<Integer> b, List<Integer> c, int n)。關于List<Integer>如果友友還沒有學到的話可以把他看成一個數組。

3.只關心某一個子問題是如何解決的(函數體)

我們取第三層漢諾塔來研究(大問題被拆成3層漢諾塔)。

我們發現子問題剛來三件事

1.把A上面n - 1 個盤子通過C移動到B?

2.把A上面最后一個盤中移動到C

3.把B上面n - 1個盤中通過A 移動到C

dfs(a, c, b, n - 1);

c.add(a.remove(a.size() - 1));//這里是因為給出的例題這樣做就是把盤中從A移動到C(理解思路即可)

dfs(b, a, c, n - 1);

4.遞歸出口

當問題的規模變為n=1時,即只有?個盤?時,我們可以直接將其從A柱移動到C柱。

本例題代碼實現如下:

class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {dfs(A,B,C,A.size());}public void dfs(List<Integer> A, List<Integer> B, List<Integer> C,int n ){if(n == 1){C.add(A.remove(A.size() - 1));return;}dfs(A,C,B,n - 1);C.add(A.remove(A.size() - 1));dfs(B,A,C,n - 1);}
}

關于本例題要注意的點:c.add(a.remove(a.size() - 1));可能有的友友會糾結為什么不是remove(0)呢,其實自己模擬一下即可,我們移走盤子是從最上面那個盤子開始移動的。

不用太深究函數的細節(陷入將無法自拔),如果是第一次的話可以去b站上看看遞歸的全過程細節(這里的不用深究是建立在已經對它的展開有一定理解了,第一次學漢諾塔的話我還是建議大家可以看看別人推的整個過程,理解更加深刻)。

例題2:合并兩個有序鏈表

鏈接:合并兩個有序鏈表

題目簡介:

將兩個升序鏈表合并為一個新的?升序?鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。?

解法:

通過分析題目我們發現可以把大問題拆成下圖的子問題,上面的1已經合并有序現在要讓2,4和下面鏈表合并有序。

故我們可以用遞歸來解決這道問題。

1.遞歸函數的作用

交給你兩個鏈表的頭結點,你幫我把它們合并起來,并且返回合并后的頭結點.

2.相同子問題(函數頭)

由上圖可以看到函數要包含兩個鏈表還要能返回合并后的鏈表故函數頭設定為:public ListNode mergeTwoLists(ListNode l1, ListNode l2)

3.只關心某一個子問題是如何解決的(函數體)

選擇兩個頭結點中較小的結點作為最終合并后的頭結點,然后將剩下的鏈表交給遞歸函數去處理。

4.遞歸出口

當某?個鏈表為空的時候,返回另外?個鏈表。

代碼如下:

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {if(list1 == null){return list2;}if(list2 == null){return list1;}if(list1.val <= list2.val){list1.next = mergeTwoLists(list1.next,list2);return list1;}else{list2.next = mergeTwoLists(list1,list2.next);return list2;}}
}

例題3:反轉鏈表

鏈接:反轉鏈表

題目簡介:

給你單鏈表的頭節點?head?,請你反轉鏈表,并返回反轉后的鏈表。

解法:

要想讓1到5逆序,可以讓5逆序后讓1到4逆序一直這樣下去我們不難發現這就是遞歸。

1.遞歸函數的作用

交給你?個鏈表的頭指針,你幫我逆序之后,返回逆序后的頭結點。

2.相同子問題(函數頭)

需要傳入鏈表,5節點逆序后要把逆序后的新頭節點返回故將函數體設為public ListNode reverseList(ListNode head)

3.只關心某一個子問題是如何解決的(函數體)

先把當前結點之后的鏈表逆序,逆序完之后,把當前結點添加到逆序后的鏈表后?即可。

4.遞歸出口

當前結點為空或者當前只有?個結點的時候,不?逆序,直接返回。

代碼如下:

class Solution {public ListNode reverseList(ListNode head) {ListNode newHead = head;if(head == null){return head;}ListNode cur = head.next;ListNode prev = head;head.next = null;while(cur != null){ListNode next = cur.next;cur.next = prev;prev = cur;cur = next;}return prev;}
}

例題4:兩兩交換鏈表中的節點

鏈接:兩兩交換鏈表中的節點

題目簡介:

給你一個鏈表,兩兩交換其中相鄰的節點,并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本題(即,只能進行節點交換)。

?解法:

我們通過閱讀題目可以發現要使整個鏈表兩兩交換?,可以將大問題分為把1和2后面的節點兩兩交換,把一二交換即可,同理3和4也是同樣的處理思路。

1.遞歸函數的作用

交給你?個鏈表,將這個鏈表兩兩交換?下,然后返回交換后的頭結點;

2.相同子問題(函數頭)

需要傳入原始鏈表和返回新的頭節點故設計為:public ListNode swapPairs(ListNode head)

3.只關心某一個子問題是如何解決的(函數體)

先去處理?下第?個結點往后的鏈表,然后再把當前的兩個結點交換?下,連接上后面處理后的鏈表;

4.遞歸出口

當前結點為空或者當前只有?個結點的時候,不?交換,直接返回。

代碼如下:

class Solution {public ListNode swapPairs(ListNode head) {if(head == null || head.next == null){return head;}ListNode newHead = head.next;head.next = swapPairs(head.next.next);newHead.next = head;return newHead;}
}

例題5:Pow(x,n)-快速冪

鏈接:Pow(x,n)

題目簡介:

實現?pow(x,?n)?,即計算?x?的整數?n?次冪函數(即,xn?)。

??解法:

這題不能使用1個1個數的分離遞歸(會超時),我們這里要采用二分的思路,具體實現如下:

1.遞歸函數的作用

求出x 的n 次?是多少,然后返回;

2.相同子問題(函數頭)

需要傳入需要n次方的x和n還要將其返回public double pow(double x, int n)

3.只關心某一個子問題是如何解決的(函數體)

先求出x 的n / 2 次?是多少,然后根據n 的奇偶,得出x 的n 次?是多少;

4.遞歸出口

當n 為0 的時候,返回1 即可。

代碼如下:

最上面要區分一下正負數的區別即可。

class Solution {public double myPow(double x, int n) {return (n < 0) ? 1.0 / pow(x, - n) : pow(x , n);}public double pow(double x,int n){if(n == 0){return 1.0;}double tmp = pow(x,n / 2);return (n % 2 == 0) ? tmp * tmp : tmp * tmp * x;}
}

總結:本文章是搜索回溯的第一篇,帶大家再復習了一下遞歸,后續的章節會帶領大家深度理解深搜和回溯算法。

結語:

其實寫博客不僅僅是為了教大家,同時這也有利于我鞏固自己的知識點,和一個學習的總結,由于作者水平有限,對文章有任何問題的還請指出,接受大家的批評,讓我改進,如果大家有所收獲的話還請不要吝嗇你們的點贊收藏和關注,這可以激勵我寫出更加優秀的文章。

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

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

相關文章

嵌入式驅動學習第二周——斷言機制

前言 這篇博客來聊一聊C/C的斷言機制。 嵌入式驅動學習專欄將詳細記錄博主學習驅動的詳細過程&#xff0c;未來預計四個月將高強度更新本專欄&#xff0c;喜歡的可以關注本博主并訂閱本專欄&#xff0c;一起討論一起學習。現在關注就是老粉啦&#xff01; 目錄 前言1. 斷言介紹…

貪心 Leetcode 134 加油站

加油站 Leetcode 134 學習記錄自代碼隨想錄 在一條環路上有 n 個加油站&#xff0c;其中第 i 個加油站有汽油 gas[i] 升 你有一輛油箱容量無限的的汽車&#xff0c;從第 i 個加油站開往第 i1 個加油站需要消耗汽油 cost[i] 升。你從其中的一個加油站出發&#xff0c;開始時油…

串聯所有單詞的子串

題目鏈接 串聯所有單詞的子串 題目描述 注意點 words[i] 和 s 由小寫英文字母組成1 < words.length < 5000可以以 任意順序 返回答案words中所有字符串長度相同 解答思路 根據滑動窗口哈希表解決本題&#xff0c;哈希表存儲words中所有的單詞及單詞的出現次數&#…

Reactor詳解

目錄 1、快速上手 介紹 2、響應式編程 2.1. 阻塞是對資源的浪費 2.2. 異步可以解決問題嗎&#xff1f; 2.3.1. 可編排性與可讀性 2.3.2. 就像裝配流水線 2.3.3. 操作符&#xff08;Operators&#xff09; 2.3.4. subscribe() 之前什么都不會發生 2.3.5. 背壓 2.3.6. …

p18 線性代數,行階梯型矩陣

行階梯型矩陣 行最簡型矩陣

steam游戲搬磚,跨國信息差項目,每天1小時收益也很不錯

大家好&#xff0c;我是阿陽&#xff01;每天都是一個新的開始&#xff01; 今天看到個Steam游戲搬磚項目&#xff0c;還是跨國國際貿易&#xff0c;感覺很好玩&#xff0c;特來給大家分享。 原理簡介 就是把Steam上的游戲裝備&#xff0c;搬運到國內網易Buff平臺上來賣。目前…

算法沉淀——動態規劃之01背包問題(leetcode真題剖析)

算法沉淀——動態規劃之01背包問題 01.【模板】01背包02.分割等和子集03.目標和04.最后一塊石頭的重量 II 01背包問題是一類經典的動態規劃問題&#xff0c;通常描述為&#xff1a;有一個固定容量的背包&#xff0c;以及一組物品&#xff0c;每件物品都有重量和價值&#xff0c…

c++基礎學習第二天(數組,函數)

提示&#xff1a;c基礎學習第二天&#xff08;數組&#xff0c;函數&#xff09; 文章目錄 1、數組1.1、 概述1.2、一維數組1.2.1、一維數組定義方式1.2.2、一維數組名稱的用途. 1.3、 二維數組1.3.1、二維數組定義方式1.3.2、二維數組數組名的用途 2、函數2.1、概述2.2、函數的…

云計算 2月28號 (linux的磁盤分區)

一 存儲管理 主要知識點: 基本分區、邏輯卷LVM、EXT3/4/XFS文件系統、RAID 初識硬盤 機械 HDD 固態 SSD SSD的優勢 SSD采用電子存儲介質進行數據存儲和讀取的一種技術&#xff0c;擁有極高的存儲性能&#xff0c;被認為是存儲技術發展的未來新星。 與傳統硬盤相比&#xff0c…

Vue 3 中的 Composition API 詳解

Vue.js&#xff0c;作為前端領域流行的框架之一&#xff0c;以其響應式數據綁定和組件化開發贏得了廣大開發者的喜愛。隨著前端技術的不斷發展和項目復雜度的增加&#xff0c;Vue 團隊推出了 Vue 3&#xff0c;并引入了 Composition API&#xff0c;以更好地滿足復雜應用的需求…

深度偽造,讓網絡釣魚更加難以辨別

網絡釣魚一直是安全領域的一個突出話題&#xff0c;盡管這類詐騙形式已經存在了幾十年&#xff0c;依舊是欺詐攻擊或滲透組織的最有效方法之一。詐騙分子基于社會工程原理&#xff0c;通過郵件、網站以及電話、短信和社交媒體&#xff0c;利用人性&#xff08;如沖動、不滿、好…

嵌入式驅動學習第二周——Linux內核打印

前言 這篇博客來聊一聊Linux內核打印。 嵌入式驅動學習專欄將詳細記錄博主學習驅動的詳細過程&#xff0c;未來預計四個月將高強度更新本專欄&#xff0c;喜歡的可以關注本博主并訂閱本專欄&#xff0c;一起討論一起學習。現在關注就是老粉啦&#xff01; 目錄 前言1. dmesg指令…

react diff

react diff算法為降低算法復雜度提出了三大策略&#xff1a; 1.只進行同級比較 2.節點類型比較&#xff0c;不同元素生成不同的fiber樹 3.key作為元素的唯一標識 diff算法流程 diff算法需要進行兩輪遍歷&#xff1a; 第一輪遍歷更新的節點。 第二輪遍歷沒更新的節點。 第一輪…

【LeetCode:225. 用隊列實現棧 + 棧 | 隊列】

&#x1f680; 算法題 &#x1f680; &#x1f332; 算法刷題專欄 | 面試必備算法 | 面試高頻算法 &#x1f340; &#x1f332; 越難的東西,越要努力堅持&#xff0c;因為它具有很高的價值&#xff0c;算法就是這樣? &#x1f332; 作者簡介&#xff1a;碩風和煒&#xff0c;…

水牛社軟件是真的嗎?

軟件是真的&#xff0c;不過畢竟是為了賺錢或者獲取資源而買的&#xff0c;所以大部分只關心能賺多少錢吧 說實話&#xff0c;我用了2年了&#xff0c;一些獨立的項目還有群&#xff0c;有一月掙幾千上萬的&#xff0c;有一月賺幾百的 軟件是一個集合體&#xff0c;不是像很多…

【leetcode刷題之路】面試經典150題(5)——二叉樹+二叉樹層次遍歷+二叉搜索樹

文章目錄 9 二叉樹9.1 【遞歸】二叉樹的最大深度9.2 【遞歸】相同的樹9.3 【遞歸】翻轉二叉樹9.4 【遞歸】對稱二叉樹9.5 【遞歸】從前序與中序遍歷序列構造二叉樹9.6 【遞歸】從中序與后序遍歷序列構造二叉樹9.7 【BFS】填充每個節點的下一個右側節點指針 II9.8 【遞歸】二叉樹…

代碼隨想錄第二十七天 455.分發餅干 376.擺動序列 53.最大子序和 122.買賣股票的最佳時機II

LeetCode 455 分發餅干 題目描述 假設你是一位很棒的家長&#xff0c;想要給你的孩子們一些小餅干。但是&#xff0c;每個孩子最多只能給一塊餅干。 對每個孩子 i&#xff0c;都有一個胃口值 g[i]&#xff0c;這是能讓孩子們滿足胃口的餅干的最小尺寸&#xff1b;并且每塊餅…

2024全國護網行動HW行動招聘/收人!!!

2024全國護網行動HW行動招聘 溯蓉信創開始收人啦&#xff01;&#xff01;&#xff01;現在開始收錄2024HW簡歷&#xff0c;感興趣的小伙伴掃碼二維碼添加微信 我們簽約后&#xff0c;入場即預付款3k&#xff0c;簽約后我們會在HW之前對我們的人員進行HW培訓&#xff0c;保證上…

Three.js--》探尋Cannon.js構建震撼的3D物理交互體驗(一)

我們用three.js可以繪制出各種酷炫的畫面&#xff0c;但是當我們想要一個更加真實的物理效果的話&#xff0c;這個時候我們就需要一個物理的庫&#xff0c;接下來我們就講解一下今天要學習的canon&#xff0c;它可以給我們提供一個更加真實的物理效果&#xff0c;像物體的張力、…

YOLOv8姿態估計實戰:訓練自己的數據集

課程鏈接&#xff1a;https://edu.csdn.net/course/detail/39355 YOLOv8 基于先前 YOLO 版本的成功&#xff0c;引入了新功能和改進&#xff0c;進一步提升性能和靈活性。YOLOv8 同時支持目標檢測和姿態估計任務。 本課程以熊貓姿態估計為例&#xff0c;將手把手地教大家使用C…