LeetCode 每日一題 [11] 反轉(zhuǎn)鏈表

LeetCode 反轉(zhuǎn)鏈表 [簡(jiǎn)單]

反轉(zhuǎn)一個(gè)單鏈表。

來(lái)源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/reverse-linked-list

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

進(jìn)階:

你可以迭代或遞歸地反轉(zhuǎn)鏈表。你能否用兩種方法解決這道題?

題目分析:
解法1:

先把 node 中的數(shù)據(jù)取出來(lái)存放到集合中,然后再?gòu)募现腥〕鰯?shù)據(jù),再創(chuàng)建ListNode 放進(jìn)去。這樣使用和額外的空間,肯定不是最優(yōu)解。面試官肯定會(huì)追問(wèn)的。

解法2:

根據(jù)題目的提示,可以使用迭代或者遞歸,那么使用迭代如何實(shí)現(xiàn)呢?
在遍歷鏈表的時(shí)候,將當(dāng)前節(jié)點(diǎn)的 next 指向前一個(gè)元素,由于節(jié)點(diǎn)沒(méi)有引用上一個(gè)節(jié)點(diǎn),因此必須事先存儲(chǔ)其前一個(gè)元素,我們可以申請(qǐng)兩個(gè)指針,第一個(gè)指針叫 pre,最初是指向 null 的。每次迭代到 cur,都將 cur 的 next 指向 pre,然后 pre 和 cur 前進(jìn)一位。第二個(gè)指針 cur 指向 head,然后不斷遍歷 cur。都迭代完了(cur 變成 null 了),pre 就是最后一個(gè)節(jié)點(diǎn)了。

圖示

解法3:

遞歸的兩個(gè)條件:
終止條件是當(dāng)前節(jié)點(diǎn)或者下一個(gè)節(jié)點(diǎn)==null
在函數(shù)內(nèi)部,改變節(jié)點(diǎn)的指向,也就是 head 的下一個(gè)節(jié)點(diǎn)指向 head 遞歸函數(shù)那句

head.next.next = head

很不好理解,其實(shí)就是 head 的下一個(gè)節(jié)點(diǎn)指向head。
遞歸函數(shù)中每次返回的 cur 其實(shí)只最后一個(gè)節(jié)點(diǎn),在遞歸函數(shù)內(nèi)部,改變的是當(dāng)前節(jié)點(diǎn)的指向。

代碼實(shí)現(xiàn)
public class LeetCode_11_ReverseLinkedList {

    public static void main(String[] args) {

    }

    //也可以申請(qǐng)額外的空間 但是肯定不是最優(yōu)解

    public ListNode reverseList01(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        //這里的 curr 就是最后一個(gè)節(jié)點(diǎn)
        ListNode curr = reverseList01(head.next);
        //如果鏈表是 1->2->3->4->5,那么此時(shí)的cur就是5
        //而head是4,head的下一個(gè)是5,下下一個(gè)是空
        //所以head.next.next 就是5->4
        head.next.next = head;
        //防止鏈表循環(huán),需要將head.next設(shè)置為空
        head.next = null;
        //每層遞歸函數(shù)都返回cur,也就是最后一個(gè)節(jié)點(diǎn)
        return curr;
    }

    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode curr = head;
        ListNode next = null;
        while (curr != null) {
            //存儲(chǔ)下一個(gè)需要移動(dòng)的指針位置
            next = curr.next;
            //然后將當(dāng)前節(jié)點(diǎn)指向pre
            curr.next = pre;
            //新的頭指針向后移動(dòng)
            pre = curr;
            //頭指針向后移動(dòng)
            curr = next;
        }
        return pre;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。