(一)基础:链表反转问题
(1)三指针。使用三个指针,分别指向当前遍历到的结点、它的前一个结点以及后一个结点。将指针反转后,三个结点依次前移即可。(2)递归方法。同样可以采用递归来实现反转。将头结点之后的链表反转后,再将头结点接到尾部即可。
//方法一:三指针
public ListNode ReverseList(ListNode head) {
if(head==null)
return null;
ListNode first=null;
ListNode second=head;
ListNode third=head.next;
while(third!=null){
second.next=first; //三指针之间的变换
first=second;
second=third;
third=third.next;
}
second.next=first;
return second;
}
//方法二:递归
public ListNode ReverseList(ListNode head) {
if(head==null||head.next==null)
return head;
ListNode temp=ReverseList(head.next);
head.next.next=head;
head.next=null;
return temp;
}
(二)反转链表II(从m到n)
题目(Medium):92. 反转链表 II
题目描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
解题思路:
本题是链表反转的一个延伸,实际上,只要理清楚每一个指针的变化,并不难实现。如下图所示,
第一步:找到待反转节点的前一个节点。
第二步:反转m到n这部分。
第三步:将反转的起点的next指向反转的后面一部分。
第四步:将第一步找到的节点指向反转以后的头节点。

图片来自:作者:reedfan
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/ji-bai-liao-100de-javayong-hu-by-reedfan-6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
代码实现:
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
if(head==null || head.next==null)
return head;
ListNode phead=new ListNode(-1); //头结点
phead.next=head;
ListNode firstTail=null,cur=phead;
//走m步,则cur是第m个结点,pre是反转之前最后一个,也就是正常一段的末尾
for(int i=0;i<m;i++){
firstTail=cur;
cur=cur.next;
}
ListNode reverseTail=cur;
//三指针法,反转从m到n的这一段
ListNode pre=null,third=cur.next;
for(int i=m;i<=n;i++){
cur.next=pre;
pre=cur;
cur=third;
if(third!=null)
third=third.next;
}
reverseTail.next=cur;
firstTail.next=pre;
return phead.next;
}
}
(三)K个一组反转链表
题目(hard):25. K 个一组翻转链表
题目描述:
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解题思路:
本题难度相对较大,在前面两题的基础上进一步思考,关键是指针的移动和变化要理解清楚。主要通过下图来展示:

图片来自:作者:deppwang-2
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/solution/25-k-ge-yi-zu-fan-zhuan-lian-biao-by-deppwang-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
代码实现:
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null || head.next==null)
return head;
ListNode phead=new ListNode(-1);
phead.next=head;
ListNode pre=phead,end=phead;
while(end.next!=null){
for(int i=0;i<k;i++){
if(end!=null)
end=end.next;
}
if(end==null)
break;
ListNode temp=end.next; //记录下一次的起点
end.next=null; //断开
ListNode start=pre.next;
pre.next=reverse(start); //反转
start.next=temp;
pre=start;
end=start;
}
return phead.next;
}
//链表反转
public ListNode reverse(ListNode head){
if(head==null || head.next==null)
return head;
ListNode first=null,second=head,third=head.next;
while(third!=null){
second.next=first;
first=second;
second=third;
third=third.next;
}
second.next=first;
return second;
}
}
总结:
以上三道题以反转链表为基础,层层递进,是链表类题目中的典型问题,其主要的核心在于理清楚每一个指针的变化情况,同时要时刻注意头结点的使用和防止空指针。