前言
链表刷题结束。
1、题目1:24-两两交换链表中的节点
类型:中等
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
代码:
public static ListNode swapPairs(ListNode head) {
ListNode dummp = new ListNode(0);
dummp.next = head;
ListNode curr = dummp;
while (curr.next!=null && curr.next.next!=null){
ListNode first = curr.next;
ListNode next = curr.next.next;
ListNode temp = next.next;
curr.next = next;
next.next = first;
first.next = temp;
curr=curr.next.next;
}
return dummp.next;
}
2、题目2:19-删除链表的倒数第N个节点
难度:简单
思路:
双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode();
dummy.next =head;
ListNode fast=dummy,curr=dummy;
for (int i = 0; i < n; i++) {
curr = curr.next;
}
while (curr.next!=null){
curr = curr.next;
fast = fast.next;
}
fast.next = fast.next.next;
return dummy.next;
}
3、题目3:160-链表相交
类型:简单
链表如果相交,那相交的位置就是 C1,难点在于使用两个指针,如何让它们同时达到 C1 节点,
假设:设置 a 的长度是 x+z ;b 的长度是 y+z。
- x+z = y+z
- x+z+y = y+z+x
即,双指针,A 指针当遍历完 A 链表,再遍历 B 链表;B 指针遍历 B 链表后再遍历 A 链表后,
此时存在首个相交的节点,要么存在,要么为null,返回这个值即可。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p1 =headA,p2=headB;
while (p1!=p2){
// p1 走一步,如果走到 A 链表末尾,转到 B 链表
if(p1 == null){
p1=headB;
}else{
p1=p1.next;
}
if(p2 == null){
p2=headA;
}else{
p2 =p2.next;
}
}
return p1;
}
}
4、题目4:142-环形链表II
类型:中等
又是个需要分析和计算的题目。
这个环形问题,就是让两指针分别以1慢1快的速度开始。
Slow 指针每次走1步,fast 指针每次走2步,找到相遇点后,让某个指针回到head节点行走k-m即到环的节点位置。
ListNode fast,slow;
fast = slow = head;
while (fast!=null && fast.next!=null){
fast = fast.next.next;
slow=slow.next;
if(fast == slow){
break;
}
}
// fast 代表遇到空指针
if(fast == null || fast.next == null){
return null;
}
slow = head;
while (slow!=fast){
fast = fast.next;
slow=slow.next;
}
return slow;
5、总结
链表的经典题目页都刷过了,关于是否要添加虚拟头结点 :虚拟头结点的主要目的是为了避免对头结点的特殊处理;这个处理就指的是修改操作。所以可以这样:涉及到对链表修改(如插入,删除,移动)的,都加个dummy,只是遍历取点就可以不用加。