- 额外设置一个虚拟节点,next指向头结点,方便操作链表
剑指 Offer II 021. 删除链表的倒数第 n 个结点
- 需要保留被删除节点的上一个节点
- 双指针 fast 比 slow 先跑 n+1,当fast指向null时,slow就指向被删除节点的前驱
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null){
return null;
}
ListNode cur = new ListNode(0,head);
// fast = slow + n+1 当fast==null 时, slow指向的就是要被删除的节点的前驱结点
ListNode slow = cur;
ListNode fast = cur;
int count = 0;
slow = cur;
fast = cur;
while(fast!=null ){
if(count<n+1){
fast = fast.next;
count++;
}else{
fast = fast.next;
slow = slow.next;
}
}
slow.next = slow.next.next;
//
// 一开始 return head 肯定错了 因为head一直指向原始头节点
return cur.next;
}
}
移除元素
- [] —> null
- [0] —> new ListNode();
206 翻转链表
- 头插法
24. 两两交换链表中的节点
- 纸上画出链表 模拟变换过程
- 注意 c = node 和 c.next = node 的区别
- 前者是获取到节点的地址 , 可以直接通过 c 操作节点
- 后者只是将尾指针指向node,操作c不会对node造成影响
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null){
return null;
}
if(head.next == null){
return head;
}
ListNode current = new ListNode(0,head);
ListNode d = new ListNode();
while( current.next!=null && current.next.next != null){
ListNode a = current.next;
ListNode b = current.next.next;
ListNode c = current.next.next.next;
if(current.next == head){
head = b;
}else{
d.next = b;
}
a.next = c;
b.next = a;
d = a;
current.next = c;
}
return head;
}
}