遞歸反轉(zhuǎn)鏈表,怎么就不會了呢
Python實戰(zhàn)社群
Java實戰(zhàn)社群
長按識別下方二維碼,按需求添加
掃碼關(guān)注添加客服
進(jìn)Python社群▲
掃碼關(guān)注添加客服
進(jìn)Java社群▲
LeetCode?#206?反轉(zhuǎn)鏈表 LeetCode?#92 反轉(zhuǎn)鏈表||
01
LeetCode #206 反轉(zhuǎn)鏈表



public ListNode reverseList(ListNode head) {// 調(diào)用遞推公式反轉(zhuǎn)當(dāng)前結(jié)點之后的所有節(jié)點// 返回的結(jié)果是反轉(zhuǎn)后的鏈表的頭結(jié)點ListNode newHead = reverseList(head.next);}

最后,將head指向的結(jié)點的下一個結(jié)點置為null,就完成了整個鏈表的反轉(zhuǎn)。

將反轉(zhuǎn)head指向的結(jié)點的代碼完善之后,就可以得到如下的代碼:
public ListNode reverseList(ListNode head) {// 調(diào)用遞推公式反轉(zhuǎn)當(dāng)前結(jié)點之后的所有節(jié)點// 返回的結(jié)果是反轉(zhuǎn)后的鏈表的頭結(jié)點ListNode newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;}
遞歸調(diào)用這一部分完成之后,還有重要的一步就是遞歸終止條件,遞歸反轉(zhuǎn)鏈表什么時候停止呢?在head指向的結(jié)點為null或head指向的結(jié)點的下一個結(jié)點為null時停止,因為在這兩種情況下,反轉(zhuǎn)后的結(jié)果就是它自己。到這里,就可以寫出完整的代碼了:
public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {return head;}// 調(diào)用遞推公式反轉(zhuǎn)當(dāng)前結(jié)點之后的所有節(jié)點// 返回的結(jié)果是反轉(zhuǎn)后的鏈表的頭結(jié)點ListNode newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;}
02
LeetCode #92?反轉(zhuǎn)鏈表||
1 ≤ m ≤ n ≤ 鏈表長度。
輸入: 1->2->3->4->5->NULL, m = 2, n = 4
輸出: 1->4->3->2->5->NULL
為了方便說明一個問題,這里以鏈表1->2->3->4->5->6->NULL, m = 3, n = 5為例進(jìn)行分析如何用遞歸思想求解該題目。


public ListNode reverseBetween(ListNode head, int m, int n) {ListNode between = reverseBetween(head.next, m-1,n-1);}

public ListNode reverseBetween(ListNode head, int m, int n) {ListNode between = reverseBetween(head.next, m-1,n-1);head.next = between;return head;}
遞推公式的部分已經(jīng)完成了,接著要明確的就是遞歸終止條件。在這里原問題是反轉(zhuǎn)鏈表:1->2->3->4->5->6->NULL, m = 3, n = 5之間的部分。
更小的子問題是反轉(zhuǎn)鏈表:2->3->4->5->6->NULL, m = 2, n = 4之間的部分。
在進(jìn)一步是反轉(zhuǎn)鏈表:3->4->5->6->NULL, m = 1, n = 3之間的部分。但是,這時這個子問題和上一個子問題還是可以用相同思路求解的同一個子問題嗎?

public ListNode reverseBetween(ListNode head, int m, int n) {if (m == 1) {return 待補(bǔ)充;}ListNode between = reverseBetween(head.next, m-1,n-1);head.next = between;return head;}

這里,遞推公式reverseTopN的含義是反轉(zhuǎn)鏈表的前n個結(jié)點并返回被反轉(zhuǎn)的鏈表的頭結(jié)點。因此,其需要的參數(shù)有兩個,一是待反轉(zhuǎn)的鏈表的頭結(jié)點,二是反轉(zhuǎn)前幾個結(jié)點,即n。


至此,對于反轉(zhuǎn)鏈表的前n個結(jié)點,可以初步寫出如下的代碼:
private ListNode reverseTopN(ListNode head, int n) {ListNode newHead = reverseTopN(head.next, n-1);}
經(jīng)過前面分析,我們知道head指向的結(jié)點3也是需要反轉(zhuǎn)的,即head.next.next=head。但是,我們發(fā)現(xiàn)在完成這一步操作后,結(jié)點6沒法在和其它結(jié)點產(chǎn)生聯(lián)系了。


這時,在反轉(zhuǎn)結(jié)點3,即head.next.next=head之后,我們可以將topNSuccessor指向的結(jié)點掛在head指向的結(jié)點之后,即head.next=topNSuccessor。


這時,反轉(zhuǎn)鏈表前N個結(jié)點的代碼進(jìn)一步完善如下:
private ListNode reverseTopN(ListNode head, int n) {ListNode newHead = reverseTopN(head.next, n-1);head.next.next = head;head.next = topNSuccessor;return newHead;}

ListNode topNSuccessor = null;private ListNode reverseTopN(ListNode head, int n) {if (n == 1) {topNSuccessor = head.next;return head;}ListNode newHead = reverseTopN(head.next, n-1);head.next.next = head;head.next = topNSuccessor;return newHead;}
public ListNode reverseBetween(ListNode head, int m, int n) {if (m == 1) {return reverseTopN(head, n);}ListNode between = reverseBetween(head.next, m-1,n-1);head.next = between;return head;}ListNode topNSuccessor = null;private ListNode reverseTopN(ListNode head, int n) {if (n == 1) {topNSuccessor = head.next;return head;}ListNode newHead = reverseTopN(head.next, n-1);head.next.next = head;head.next = topNSuccessor;return newHead;}
題圖:rahu / Pixabay


近期精彩內(nèi)容推薦:??


