国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解

這篇具有很好參考價值的文章主要介紹了遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、遞歸

1.1 什么是遞歸?

下面是來自百度百科對遞歸算法的定義:

?遞歸是一種算法設(shè)計技術(shù),它允許一個函數(shù)在其定義或說明中有直接或間接調(diào)用自身的方法。
?遞歸在數(shù)學(xué)和計算機(jī)科學(xué)中有著廣泛的應(yīng)用,它通過將復(fù)雜問題分解為規(guī)模較小、形式相同的子問題來求解。遞歸的基本原理包括:每一級的函數(shù)調(diào)用都有自己的變量;每一次函數(shù)調(diào)用都會有一次返回;遞歸函數(shù)中,位于遞歸調(diào)用前的語句和各級被調(diào)用函數(shù)具有相同的執(zhí)行順序;遞歸函數(shù)中,位于遞歸調(diào)用后的語句的執(zhí)行順序和各個被調(diào)用函數(shù)的順序相反;雖然每一級遞歸都有自己的變量,但是函數(shù)代碼并不會得到復(fù)制。

?簡單來說,遞歸的本質(zhì)就是函數(shù)自己調(diào)用自己!

1.2 為什么會用到遞歸?

?在回答這個問題前,我們先來看看二叉樹的先序遍歷是如何實現(xiàn)的?

?所謂先序遍歷即依次遍歷二叉樹的根節(jié)點、左子樹、右子樹。在遍歷過程中,我們發(fā)現(xiàn)左子樹和右子樹的遍歷同樣可以采用先序遍歷來實現(xiàn)。即將先序遍歷整顆二叉樹轉(zhuǎn)化先遍歷完根節(jié)點后,在先序遍歷來遍歷左子樹、右子樹。而在先序遍歷左/右子樹時,我們可以將左子樹和右子樹當(dāng)成一顆完整的二叉樹,重復(fù)上述的過程,直到為空才結(jié)束。

? 在求解問題時,我們發(fā)現(xiàn)可以將主問題可以分解為若干個相同的子問題,而這些子問題同樣都可以分解為若干個相同的子子問題,不斷重復(fù)。換句話說,假設(shè)我們可以通過一個方法f(可以將f想象成數(shù)學(xué)中求解問題的函數(shù)表達(dá)式f(x))來求解主問題,而主問題所轉(zhuǎn)化出的子問題同樣可以通過方法f來解決(而子問題所衍生出的子子問題同樣可以通過方法f來解決,不斷重復(fù)下去),從而實現(xiàn)函數(shù)自己調(diào)用自己!當(dāng)面臨這種情況時,即可使用遞歸算法來解決問題。

1.3 如何快速編寫正確的遞歸代碼?

  1. 找到相同的子問題,該過程決定了函數(shù)頭的設(shè)計(即函數(shù)參數(shù)需要傳哪些)
  2. 將其中一個子問題進(jìn)行分析,在此過程中將遞歸函數(shù)當(dāng)作一個黑盒,該函數(shù)能完成我們所賦予的功能。該過程決定了函數(shù)的函數(shù)體。
  3. 最后當(dāng)然是返回值了。在何種情況下,遞歸結(jié)束。

下面以二叉樹的先序遍歷為例進(jìn)行分析:
? 首先先序遍歷過程:根、左子樹、右子樹。而左子樹和右子樹顯然是一個相同的子問題(左子樹和右子樹還可以繼續(xù)細(xì)分下去,都行相同子問題,就不多說了)。所有我們需要給函數(shù)傳一個根節(jié)點參數(shù),用于分割整顆二叉樹

void TreePrev(TreeNode* root)//函數(shù)頭

? 現(xiàn)在我們賦予了該遞歸函數(shù)功能:先序遍歷二叉樹?,F(xiàn)在我們?nèi)∑渲幸粋€子問題進(jìn)行分析,首先我們需要遍歷根節(jié)點,然后可以通過該遞歸函數(shù)來實現(xiàn)左子樹、右子樹的先序遍歷了,即:

cout << root -> val <<" ";//根節(jié)點
//我們賦予了函數(shù)TreePrev先序遍歷二叉樹的功能,所有我們可以把該函數(shù)當(dāng)作一個黑盒。
//只要我們將二叉樹的根節(jié)點傳入該黑盒,便可實現(xiàn)這顆二叉樹的先序遍歷。(實際該過程可以由畫遞歸展開圖驗證,由于篇幅問題博主就不多說了)
TreePrev(root -> left);//遍歷左子樹
TreePrev(root -> right);//遍歷右子樹

? 最后就是遞歸什么時候結(jié)束了。顯然當(dāng)根節(jié)點未空指針時,遞歸結(jié)束。此時返回空即可

if(root == nullptr)
	return;

所以整體代碼就是:

void TreePrev(TreeNode* root)//函數(shù)頭
{
	if(root == nullptr)
		return;
	cout << root -> val <<" ";//根節(jié)點
	//我們賦予了函數(shù)TreePrev先序遍歷二叉樹的功能,所有我們可以把該函數(shù)當(dāng)作一個黑盒。
	//只要我們將二叉樹的根節(jié)點傳入該黑盒,便可實現(xiàn)這顆二叉樹的先序遍歷。(實際該過程可以由畫遞歸展開圖驗證,由于篇幅問題博主就不多說了)
	TreePrev(root -> left);//遍歷左子樹
	TreePrev(root -> right);//遍歷右子樹	
}

二、力扣相關(guān)筆試題解析

面試題 08.06. 漢諾塔問題

遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸
【分析】:
?題目指讓A柱子中的N個圓盤(自下而上降序)借助B轉(zhuǎn)移到C柱子上,并且保存順序不變。所以我們可以考慮將A柱子上的后N-1個圓盤當(dāng)作一個整體移到B上,然后將A中剩余的最后一個圓盤移到C上;最后在將B盤上的所有圓盤當(dāng)作一個整體移到C上即可達(dá)成目的!
?在題目的分析過程中,出現(xiàn)將A上的N-1個圓盤移到B上,將B上的N-1個圓盤移到C上的過程。而這兩個步驟顯然是一個遞歸子問題(將一個柱子上的N個圓盤,借助另一個柱子轉(zhuǎn)移到第三個柱子)。由于該過程中是具體圓盤在3根柱子間的移到,所以函數(shù)頭因有4個參數(shù):柱A、柱B、柱C、移到圓盤個數(shù)??!

?由于該過程中,我們通過遞歸函數(shù)(黑盒)將A柱上的N-1個圓盤移到B柱上、將A柱上的剩余的最后一個圓盤移到C柱、通過遞歸函數(shù)(黑盒)將B中的所有圓盤移到C柱。所以函數(shù)體為:

//_hanota為我們待實現(xiàn)的遞歸函數(shù),該函數(shù)的功能是將將一個柱子上的N個圓盤,借助另一個柱子轉(zhuǎn)移到第三個柱子
//所以將該函數(shù)想成一個黑盒,只需向該函數(shù)傳遞正確參數(shù),即可實現(xiàn)對應(yīng)的功能?。ň唧w由函數(shù)展開圖證明)
//先將A中前num-1個圓盤借助C移到B
_hanota(A, C, B, num - 1);
//將A剩余的最后一個元素移到C柱子
C.push_back(A.back());
A.pop_back();
//將B上的num-1個圓盤借助A移到C柱子上
_hanota(B, A, C, num - 1);

?最后返回值就不多說了,A中只有一個圓盤時,無需解決B,直接將圓盤從A移到C上。

【下面是其中一個子問題的圓盤轉(zhuǎn)移過程圖解】:
遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸
【代碼編寫】:

class Solution {
public:
    void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {
        _hanota(A, B, C, A.size());
    }
    void _hanota(vector<int>& A, vector<int>& B, vector<int>& C, int num) 
    {
        if(num == 1)
        {
            C.push_back(A.back());
            A.pop_back();
            return;
        }
        //先將A中前num-1個圓盤借助C移到B
        _hanota(A, C, B, num - 1);
        //將A剩余的最后一個元素移到C柱子
        C.push_back(A.back());
        A.pop_back();
        //將B上的num-1個圓盤借助A移到C柱子上
        _hanota(B, A, C, num - 1);
    }
};

21. 合并兩個有序鏈表

【題目】:
遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸
【解析】:
?這道題目的就是將兩個升序的鏈表合并成一個升序鏈表,并返回新鏈表的頭節(jié)點。
?在本題中,我們可以先選出兩鏈表中節(jié)點值較小的節(jié)點,然后想辦法將該鏈表中剩下的節(jié)點和另一條鏈表合并為升序鏈表;最后將最開始選出的較小節(jié)點的next指向該新合并的新節(jié)點即可解決問題。顯然將該鏈表中剩下的節(jié)點和另一條鏈表合并為升序鏈表就是一個遞歸子問題,所以可以采用遞歸方式解決問題。
?由于遞歸子問題是合并兩個有序鏈表,所有函數(shù)頭傳的參數(shù)為待合并的兩個鏈表頭節(jié)點。至于函數(shù)體,我們只需挑選出原來兩鏈表中頭節(jié)點值較小的節(jié)點作為新鏈表的頭節(jié)點,然后通過遞歸函數(shù)將剩下的元素和另一個鏈表合并,最后將新鏈表的頭節(jié)點的next指向合并鏈表的頭節(jié)點。當(dāng)鏈表節(jié)點為空時,遞歸結(jié)束。

【代碼解析】:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
    	//特殊處理
        if (list1 == nullptr)
            return list2;
        if (list2 == nullptr)
            return list1;
         
        if (list1->val < list2->val)
        {
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        }
        else
        {
            list2->next = mergeTwoLists(list1, list2->next);
            return list2;
        }
    }
};

LCR 024. 反轉(zhuǎn)鏈表

遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸
反轉(zhuǎn)鏈表我們可以將后n-1個節(jié)點反轉(zhuǎn)(并返回反轉(zhuǎn)后鏈表的頭節(jié)點),然后在將原鏈表的頭結(jié)合和新鏈表鏈接即可。
遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head->next == nullptr)
            return head;
        ListNode* newhead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newhead;
    }
}

24. 兩兩交換鏈表中的節(jié)點

遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸
這道題本質(zhì)上和反轉(zhuǎn)鏈表類似,我們可以先將原鏈表頭兩個節(jié)點反轉(zhuǎn),然后利用遞歸子問題將后續(xù)所有節(jié)點當(dāng)成一個完成鏈表,完成兩兩交換鏈表中的節(jié)點。最后將交換后的鏈表和原鏈表的頭兩個數(shù)據(jù)鏈接即可。(如果鏈表為空,或只有一個元素,則遞歸結(jié)束)

遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解,算法指南,leetcode,算法,職場和發(fā)展,學(xué)習(xí)和成長,遞歸文章來源地址http://www.zghlxwxcb.cn/news/detail-845252.html

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return head;
        ListNode* newhead = head->next;
        head->next = swapPairs(newhead->next);
        newhead->next = head;
        return newhead;
    }
};

到了這里,關(guān)于遞歸究竟是什么?如何快速編寫正確的遞歸代碼? —— 力扣經(jīng)典面試題詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Linux:進(jìn)程等待究竟是什么?如何解決子進(jìn)程僵尸所帶來的內(nèi)存泄漏問題?

    Linux:進(jìn)程等待究竟是什么?如何解決子進(jìn)程僵尸所帶來的內(nèi)存泄漏問題?

    ?進(jìn)程等待通常是指: 父進(jìn)程通過wait()/waitpid()的方式,讓父進(jìn)程對子進(jìn)程進(jìn)行資源回收的等待過程??! ?進(jìn)程等待通常是為了解決以下兩種情況: 解決子進(jìn)程僵尸所帶來的內(nèi)存泄漏問題,對僵尸子進(jìn)程進(jìn)行資源回收! 原因在于當(dāng)子進(jìn)程僵尸后,便“刀槍不入”了。即使是

    2024年04月16日
    瀏覽(31)
  • 【數(shù)據(jù)結(jié)構(gòu)】論如何拿捏快速排序?(含非遞歸)

    【數(shù)據(jù)結(jié)構(gòu)】論如何拿捏快速排序?(含非遞歸)

    目錄 一,快速排序(遞歸) 1,快排思想 2,霍爾排序 3,挖坑法 4,前后指針法 5,快速排序優(yōu)化 1,三數(shù)取中法選key 2,小區(qū)間優(yōu)化 二,快速排序(非遞歸) Stack.h Stack.c 三,快速排序源代碼 1,快排思想 快速排序是 Hoare于1962年 提出的一種 二叉樹結(jié)構(gòu)的交換 排序方法,其

    2024年02月08日
    瀏覽(29)
  • 【數(shù)據(jù)結(jié)構(gòu)與算法】如何對快速排序進(jìn)行細(xì)節(jié)優(yōu)化以及實現(xiàn)非遞歸版本的快速排序?

    【數(shù)據(jù)結(jié)構(gòu)與算法】如何對快速排序進(jìn)行細(xì)節(jié)優(yōu)化以及實現(xiàn)非遞歸版本的快速排序?

    君兮_的個人主頁 即使走的再遠(yuǎn),也勿忘啟程時的初心 C/C++ 游戲開發(fā) Hello,米娜桑們,這里是君兮_,國慶長假結(jié)束了,無論是工作還是學(xué)習(xí)都該回到正軌上來了,從今天開始恢復(fù)正常的更新頻率,今天為大家?guī)淼膬?nèi)容是快速排序的兩大優(yōu)化和非遞歸實現(xiàn) 好了廢話不多說,開

    2024年02月08日
    瀏覽(26)
  • Git第十講 Git如何正確使用log快速查找內(nèi)容/提交

    在Git中,你可以使用不同的命令來快速查找指定內(nèi)容或指定提交。下面我將介紹兩種常用的方法。 要快速查找包含特定內(nèi)容的文件或代碼行,可以使用 git grep 命令。它類似于常見的 grep 命令,但是專門用于搜索Git倉庫中的文件。 以下是使用 git grep 命令的示例: 在上述命令

    2024年02月09日
    瀏覽(36)
  • 如何正確看待低代碼

    低代碼(Low-Code)是一種軟件開發(fā)方法,旨在通過最小化手動編碼工作,使用圖形用戶界面和可視化建模工具,從而加速應(yīng)用程序的開發(fā)過程。低代碼平臺提供了可視化的開發(fā)環(huán)境,讓開發(fā)人員使用圖形界面和少量的手動編碼來創(chuàng)建應(yīng)用程序。 主要的低代碼平臺特征包括:

    2024年02月03日
    瀏覽(13)
  • 【Algorithm】動態(tài)規(guī)劃和遞歸問題:動態(tài)規(guī)劃和遞歸有什么區(qū)別?如何比較遞歸解決方案和它的迭代版本?

    【Algorithm】動態(tài)規(guī)劃和遞歸問題:動態(tài)規(guī)劃和遞歸有什么區(qū)別?如何比較遞歸解決方案和它的迭代版本?

    動態(tài)規(guī)劃(Dynamic Programming,DP)和遞歸(Recursion)是解決復(fù)雜問題的兩種不同方法,它們在計算機(jī)科學(xué)中常用于解決具有重疊子問題和最優(yōu)子結(jié)構(gòu)特性的問題。 1.1 遞歸 (Recursion)定義及優(yōu)缺點 遞歸是一種通過將問題分解為更小的子問題來解決問題的方法。在遞歸中,一個函數(shù)

    2024年03月17日
    瀏覽(29)
  • 如何使用 ChatGPT 來快速編寫產(chǎn)品需求文檔(PRD)

    如何使用 ChatGPT 來快速編寫產(chǎn)品需求文檔(PRD)

    ChatGPT 即了解具體的編程知識,也了解編程之前的需求設(shè)計過程。因此產(chǎn)品經(jīng)理也可以使用 ChatGPT 來快速編寫PRD(產(chǎn)品需求文檔, production requirement documentation)。 首先,我們可以嘗試把需求交給 ChatGPT,發(fā)揮它的格式生成能力,快速擴(kuò)充成一篇像模像樣的 PRD 文檔。 比如我們來規(guī)

    2024年02月11日
    瀏覽(56)
  • k8s-如何快速編寫yaml文件(新手)

    k8s-如何快速編寫yaml文件(新手)

    但是這個過程并沒有在集群中執(zhí)行,只是把結(jié)果通過yaml格式的方式輸出出來,包括咱們可把它輸出到文件里 場景:適用于部署好的項目,可以把部署好的項目中的yaml文件導(dǎo)出出來,實際效果比較實用

    2024年02月13日
    瀏覽(23)
  • MVCC究竟是什么?

    MVCC,全稱多版本并發(fā)控制 MVCC究竟是什么? 通俗的來說MVCC就是為了在讀取數(shù)據(jù)時不加鎖來提高讀取效率的一種辦法,MVCC解決的是讀寫時線程安全問題,線程不用去搶占讀寫鎖。MVCC中的讀就是快照讀,也就是普通的select語句。 mvcc的具體實現(xiàn)通過數(shù)據(jù)庫中的三個隱式字段、

    2024年02月10日
    瀏覽(18)
  • 補碼究竟是什么?

    補碼究竟是什么?

    計算機(jī)底層均是通過二進(jìn)制表示數(shù)據(jù),原碼、反碼、補碼是計算機(jī)中對數(shù)字的二進(jìn)制表示方法。計算機(jī)以二進(jìn)制補碼的形式存儲整數(shù),最高位是符號位,0 表示正數(shù),1 表示負(fù)數(shù),其余位為數(shù)字位。 原碼:將最高位作為符號位(0 表示正,1 表示負(fù)),其它數(shù)字位代表數(shù)值本身

    2024年02月02日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包