一、算法题
24. 两两交换链表中的节点
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null){
return head;
}
ListNode first=new ListNode();
first.next=head;
ListNode cur=first;
//偶数节点时判断条件是cur.next!=null
//奇数节点时判断条件是cur.next.next!=null
//如果用||的话,当cur.next=null后还会继续判断cur.next.next
//此时会造成空指针异常
while(cur.next!=null&&cur.next.next!=null){
ListNode temp=cur.next;
//cur.next.next.next可能会等于null
//但是并不影响,最多就是让cur.next.next.next=null
//然后cur向后移动进入下一次循环时就会出现cur.next.next=null的情况
//所以会直接退出循环
ListNode temp1=cur.next.next.next;
cur.next=cur.next.next;
cur.next.next=temp;
cur.next.next.next=temp1;
cur=cur.next.next;
}
return first.next;
}
}
注意:
- 最后return的是first.next
- 因为head可能已经被改变
19.删除链表的倒数第N个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode first=new ListNode(-1);
first.next=head;
ListNode fast=first;
ListNode slow=first;
n++;
while(n>0){
fast=fast.next;
n--;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
return first.next;
}
}
- 双指针——快慢指针的经典应用
- fast先走n+1步,然后fast和slow同时移动,当fast=null时,此时slow移动到了被删除节点的前一个节点的位置
- 如果走n步,slow会到达被删除节点的位置,但是要进行删除得走到被删除节点的前一个位置
面试题 02.07. 链表相交
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA=headA;
ListNode curB=headB;
int lensA=0;
int lensB=0;
while(curA!=null){
lensA++;
curA=curA.next;
}
while(curB!=null){
lensB++;
curB=curB.next;
}
curA=headA;
curB=headB;
int lens=Math.abs(lensA-lensB);
if(lensA>lensB){
while(lens>0){
curA=curA.next;
lens--;
}
while(curA!=null){
if(curA==curB){
return curA;
}
curA=curA.next;
curB=curB.next;
}
return null;
}
else{
while(lens>0){
curB=curB.next;
lens--;
}
while(curB!=null){
if(curA==curB){
return curB;
}
curA=curA.next;
curB=curB.next;
}
return null;
}
}
}
注意:
- 指针存的地址,指针一样,指向一个位置,本题要比较的是结点指针不是值,不要把值和节点的概念混淆起来
- 节点是一个实例,占用一块空间,值只是它的成员变量,值怎样和节点本身没有任何关系 一个实例只由它的地址唯一确定
142.环形链表II
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null){
return null;
}
//判断是否有环
ListNode fast=head;
ListNode slow=head;
while(fast.next!=null&&fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
//找到环的起始节点
if(fast==slow){
ListNode index1=head;
ListNode index2=fast;
while(index1!=index2){
index1=index1.next;
index2=index2.next;
}
return index1;
}
}
return null;
}
}
- 判断是否存在环
- 快慢指针相遇说明一定有环
- 环的起始节点
关键点:
- x = (n - 1) (y + z) + z
- 当n=1时,说明x=z,可以推出只要一个节点从相遇节点出发,一个节点从头结点出发,最后一定会在起始处相遇。
- (n - 1) (y + z)只是说明转了多少圈
- fast指针一定要跑完一圈才有可能跟slow指针相遇
- 可以用现实生活中跑圈的思想去理解,同时出发,跑得快的人一定要跑完一圈才能超过跑的慢的人
- slow指针在第一圈就会被追上