先來看問題描述:
要想反轉一個非空單鏈表,我們必須依次調整每個節點的指針指向。
假設經過若干次調整,我們已經將 節點h之前 的指針調整完畢。但 由於節點i的指針指向 了它的前一個節點,導致我們無法在鏈表中訪問到節點j。所以,爲了這種情況的發生,我們需要在調整節點i的next指針之前,將節點j保存下來。
因此,我們需要定義三個指針,分別指向當前遍歷到的節點、它的前驅節點以及後繼節點。
給出我的代碼:
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
public class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode pPrev = null;
ListNode pNext = null;
while (head != null) {
//先用next保存head的下一個節點的信息,保證單鏈表不會因爲失去head節點的原next節點而就此斷裂
pNext=head.next;
//保存完next,就可以讓head從指向next變成指向pre
head.next = pPrev;
//head指向pre後,就繼續依次反轉下一個節點
pPrev = head;
//讓pre,head,next依次向後移動一個節點,繼續下一次的指針反轉
head = pNext;
}
return pPrev;
}
}
遞歸解法:
public class Solution{
public ListNode reverseList(ListNode head){
//如果鏈表爲空或者鏈表中只有一個元素時,直接返回頭節點
if(head==null||head.next==null){
return head;
}
//先反轉後面的鏈表,走到鏈表的末端結點
ListNode pReverseNode=reverseList(head.next);
//再將當前節點設置爲後面節點的後續節點
head.next.next=head;
head.next=null;
return pReverseNode;
}
}
再來看看這道題的進階版本:
給出相應的解法:
public class AboutLinkedList {
public ListNode reverseBetween(ListNode head, int m, int n) {
if(head==null||head.next==null){
return head;
}
//構造一個虛擬節點dummyhead,確保每個節點均有前驅節點,方便進行遍歷
ListNode dummyhead=new ListNode(-1);
dummyhead.next=head;
ListNode cur=dummyhead;
//找到要反轉子鏈表起始位置前一個節點
for(int i=0;i<m-1;i++){
cur=cur.next;
}
//對子鏈表進行反轉
ListNode f=cur.next;
ListNode s=f.next;
int j=0;
while(j<n-m
&&f!=null){
f.next = s.next;
s.next = cur.next;
cur.next = s;
s = f.next;
j++;
}
return dummyhead.next;
}
}