206. 反轉鏈表

反轉一個單鏈表。

示例:算法

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
複製代碼

進階: 你能夠迭代或遞歸地反轉鏈表。你可否用兩種方法解決這道題?bash

算法1

(鏈表操做,迭代) O(n) 翻轉即將全部節點的next指針指向前驅節點。 因爲是單鏈表,咱們在迭代時不能直接找到前驅節點,因此咱們須要一個額外的指針保存前驅節點。同時在改變當前節點的next指針前,不要忘記保存它的後繼節點。函數

空間複雜度分析:遍歷時只有3個額外變量,因此額外的空間複雜度是 O(1)。 時間複雜度分析:只遍歷一次鏈表,時間複雜度是 O(n)。this

JS代碼

/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */
/** * @param {ListNode} head * @return {ListNode} */
var reverseList = function(head) {
    if(!head) return null;
    let a = head, b = a.next;
    while(b) {
        let c = b.next;
        b.next = a;
        a = b, b = c;
    }
    head.next = null;
    return a;
};
複製代碼

例如:鏈表 [1,2,3,4,5]

  1. while 第一次執行
b = 2 -> 3 -> 4 -> 5, c = 3 -> 4 -> 5
b.next = a;
b = 2 -> 1
a = b, b = c;
a = 2 -> 1, b = 3 -> 4 -> 5
複製代碼
  1. while 第二次執行
c = 4 -> 5
b.next = a;
b = 3 -> 2 -> 1
a = b, b = c;
a = 3 -> 2 -> 1, b = 4 -> 5
複製代碼
  1. while 第三次執行
c = 5
b.next = a;
b = 4 -> 3 -> 2 -> 1
a = b, b = c;
a = 4 -> 3 -> 2 -> 1, b = 5
複製代碼

解法2: 遞歸

(鏈表操做,遞歸) O(n) 首先咱們先考慮 reverseList 函數能作什麼,它能夠翻轉一個鏈表,並返回新鏈表的頭節點,也就是原鏈表的尾節點。 因此咱們能夠先遞歸處理 reverseList(head->next),這樣咱們能夠將以head->next爲頭節點的鏈表翻轉,並獲得原鏈表的尾節點tail,此時head->next是新鏈表的尾節點,咱們令它的next指針指向head,並將head->next指向空便可將整個鏈表翻轉,且新鏈表的頭節點是tail。spa

空間複雜度分析:總共遞歸 n 層,系統棧的空間複雜度是 O(n),因此總共須要額外 O(n) 的空間。 時間複雜度分析:鏈表中每一個節點只被遍歷一次,因此時間複雜度是 O(n)。指針

JS代碼

var reverseList = function (head) {
    if (!head || !head.next) return head;
    let tail = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return tail;
};
複製代碼

例如:鏈表 [1,2,3,4,5]

執行過程

  1. 第一次執行到tail
tail = { val: 5, next: null }
head = 4 -> 5 -> null
複製代碼
  1. 執行head.next.next = head;
head.next = tail = { val: 5, next: null }
至關於tail.next = head = 4 -> 5 -> null
複製代碼
  1. 執行代碼head.next = null
tail.next = 4 -> null
tail = 5 -> 4 -> null
複製代碼
  1. 重複1-3的過程

文章轉載自:AcWing-LeetCode 206. Reverse Linked Listcode

相關文章
相關標籤/搜索