迭代和遞歸 - leetcode 206. Reverse Linked List


Reverse Linked List,一道有趣的題目。給你一個鏈表,輸出反向鏈表。因為我用的是JavaScript提交,所以鏈表的每個節點都是一個對象。例如1->2->3,就要得到3->2->1

1、數組構造###


一個很容易想到的方法是用數組保存新構造每個節點,然后反向構造鏈表,輸出:

var reverseList = function(head) {
  var ans = [];

  while (head) {
    var node = new ListNode(head.val);
    ans.push(node);
    head = head.next;
  }

  ans.reverse();

  if (!ans.length)
    return null;

  for (var i = 0, len = ans.length; i < len - 1; i++) {
    ans[i].next = ans[i + 1];
  }

  return ans[0];
};

雖然能AC,但是浪費了空間,我們幻想能不能直接把指針指向扭轉過來?

2、迭代##


迭代的精髓在於按順序對指針指向的扭轉。以1->2->3->4為例,當迭代到第三次時,前面的運算已經保存了一個pre值,值為2->1,這時到3這個節點,只需把它的指向指到pre即可,而構成的新的鏈表3->2->1保存為pre以供下次迭代,但是因為它后面的值還要做運算,所以把它原先的指向先保存起來(為next),為了下次繼續迭代:

var reverseList = function(head) {
  var pre = null;

  while (head) {
    var next = head.next;
    head.next = pre;
    pre = head;
    head = next;
  }

  return pre;
};

3、遞歸###


遞歸是迭代的好兄弟,這道題的遞歸很巧妙,想起來也有點復雜。

var reverseList = function(head) {
  if (head === null || head.next === null)
    return head;

  var next = head.next;
  head.next = null;
  var newHead = reverseList(next);
  next.next = head;

  return newHead;
};

遞歸的精髓在於將next當做參數傳入reverseList函數時,在下一次遞歸中對參數的操作,會反應在上次的參數值上。

還是以1->2->3->4舉例子,4次遞歸后(回溯前),其實是將引用鏈全部打破:

1      2      3      4
|      |      |      |
null   null  null   null

然后再添加反向的引用鏈,思路巧妙無法言喻。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM