先来看问题描述:
要想反转一个非空单链表,我们必须依次调整每个节点的指针指向。
假设经过若干次调整,我们已经将 节点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;
}
}