單鏈表的反轉是常見的面試題目。本文總結了2種方法。
1 定義
單鏈表node的數據結構定義如下:
class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } }
2 方法1:就地反轉法
2.1 思路
把當前鏈表的下一個節點pCur插入到頭結點dummy的下一個節點中,就地反轉。
dummy->1->2->3->4->5的就地反轉過程:
dummy->2->1->3->4->5 dummy->3->2->1->4->5 dummy->4>-3->2->1->5 dummy->5->4->3->2->12.2 解釋
1初始狀態
2 過程
pCur是需要反轉的節點。
- prev連接下一次需要反轉的節點
- 反轉節點pCur
- 糾正頭結點dummy的指向
- pCur指向下一次要反轉的節點
偽代碼
1 prev.next = pCur.next; 2 pCur.next = dummy.next; 3 dummy.next = pCur; 4 pCur = prev.next;
3 循環條件
pCur is not null
2.3 代碼
1 // 1.就地反轉法 2 public ListNode reverseList1(ListNode head) { 3 if (head == null) 4 return head; 5 ListNode dummy = new ListNode(-1); 6 dummy.next = head; 7 ListNode prev = dummy.next; 8 ListNode pCur = prev.next; 9 while (pCur != null) { 10 prev.next = pCur.next; 11 pCur.next = dummy.next; 12 dummy.next = pCur; 13 pCur = prev.next; 14 } 15 return dummy.next; 16 }
2.4 總結
- 1個頭結點,2個指針,4行代碼
- 注意初始狀態和結束狀態,體會中間的圖解過程。
3 方法2:新建鏈表,頭節點插入法
3.1 思路
新建一個頭結點,遍歷原鏈表,把每個節點用頭結點插入到新建鏈表中。最后,新建的鏈表就是反轉后的鏈表。
3.2 解釋
1 初始狀態
2 過程
pCur是要插入到新鏈表的節點。
pNex是臨時保存的pCur的next。
- pNex保存下一次要插入的節點
- 把pCur插入到dummy中
- 糾正頭結點dummy的指向
- pCur指向下一次要插入的節點
偽代碼
1 pNex = pCur.next 2 pCur.next = dummy.next 3 dummy.next = pCur 4 pCur = pNex
3 循環條件
pCur is not null
3.3 代碼
1 // 2.新建鏈表,頭節點插入法 2 public ListNode reverseList2(ListNode head) { 3 ListNode dummy = new ListNode(-1); 4 ListNode pCur = head; 5 while (pCur != null) { 6 ListNode pNex = pCur.next; 7 pCur.next = dummy.next; 8 dummy.next = pCur; 9 pCur = pNex; 10 } 11 return dummy.next; 12 }
3.4 總結
- 1個頭結點,2個指針(包含一個臨時保存節點的pNex),4行代碼
- 注意初始狀態和結束狀態,體會中間的圖解過程。