示例:算法
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
複製代碼
進階: 你能夠迭代或遞歸地反轉鏈表。你可否用兩種方法解決這道題?bash
(鏈表操做,迭代) O(n) 翻轉即將全部節點的next指針指向前驅節點。 因爲是單鏈表,咱們在迭代時不能直接找到前驅節點,因此咱們須要一個額外的指針保存前驅節點。同時在改變當前節點的next指針前,不要忘記保存它的後繼節點。函數
空間複雜度分析:遍歷時只有3個額外變量,因此額外的空間複雜度是 O(1)。 時間複雜度分析:只遍歷一次鏈表,時間複雜度是 O(n)。this
/** * 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;
};
複製代碼
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
複製代碼
c = 4 -> 5
b.next = a;
b = 3 -> 2 -> 1
a = b, b = c;
a = 3 -> 2 -> 1, b = 4 -> 5
複製代碼
c = 5
b.next = a;
b = 4 -> 3 -> 2 -> 1
a = b, b = c;
a = 4 -> 3 -> 2 -> 1, b = 5
複製代碼
(鏈表操做,遞歸) O(n) 首先咱們先考慮 reverseList 函數能作什麼,它能夠翻轉一個鏈表,並返回新鏈表的頭節點,也就是原鏈表的尾節點。 因此咱們能夠先遞歸處理 reverseList(head->next),這樣咱們能夠將以head->next爲頭節點的鏈表翻轉,並獲得原鏈表的尾節點tail,此時head->next是新鏈表的尾節點,咱們令它的next指針指向head,並將head->next指向空便可將整個鏈表翻轉,且新鏈表的頭節點是tail。spa
空間複雜度分析:總共遞歸 n 層,系統棧的空間複雜度是 O(n),因此總共須要額外 O(n) 的空間。 時間複雜度分析:鏈表中每一個節點只被遍歷一次,因此時間複雜度是 O(n)。指針
var reverseList = function (head) {
if (!head || !head.next) return head;
let tail = reverseList(head.next);
head.next.next = head;
head.next = null;
return tail;
};
複製代碼
tail = { val: 5, next: null }
head = 4 -> 5 -> null
複製代碼
head.next.next = head;
head.next = tail = { val: 5, next: null }
至關於tail.next = head = 4 -> 5 -> null
複製代碼
head.next = null
tail.next = 4 -> null
tail = 5 -> 4 -> null
複製代碼
文章轉載自:AcWing-LeetCode 206. Reverse Linked Listcode