算法通关村第二关——链表青铜挑战笔记
前言
全文代码均以Java语言复现,主要为自己学习做记录,如有问题,还请各位大佬们指点指点。
这篇讲解单链表增删查改中的改操作,主题是针对链表反转这一道题,多个解法。
链表反转
LeetCode24
- 方法一: 可以通过建立虚拟头结点,同时结合头插法,从而实现链表反转的效果。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dummyNode=new ListNode(-1);
ListNode cur=head;
// 不符合反转的要求的特殊情况
if(head==null|| head.next==null){
return head;
}
while(cur!=null){
ListNode next=cur.next;
// 头插法
cur.next=dummyNode.next; // 第一步 右连接
dummyNode.next=cur;// 第二步 左连接
cur=next;// 下一个
}
return dummyNode.next;
}
}
如图遍历演示 头插法的过程
- 方法二:不利用虚拟头结点,使用空的前驱节点代替虚拟头结点。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dummyNode = null;// 不指向头结点
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;//记录还没有开始头插(即节点之间位置没有变动的时候的位置)
cur.next = dummyNode;
dummyNode = cur;
cur = next;
}
return dummyNode;
}
}
如图所示,遍历执行流程图:
3. 采用递归,因为递归具有栈的特性——先进后出。
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode newNode=reverseList(head.next);
head.next.next=head;
head.next=null;
return newNode;
}
}
总结
链表的改操作,善于多画图,弄清楚节点与节点之间的连接顺序(先右后左),不使用虚拟头结点的方法,本质就是三个指针不断地移动,将指针方向“掉转枪头”,从而实现链表反转;而使用虚拟头节点,则使用到了头插法,使得链表反转,因为只有尾插法才能是链表是原数据顺序。