本题就是模拟交换的过程,为了让每个结点的操作步骤都一致,加入了虚拟头节点,交换结点的时候需要注意要先保留第三个结点即second.next。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode newhead=new ListNode();
newhead.next=head;
ListNode ptr=newhead;
while(ptr.next!=null&&ptr.next.next!=null){
ListNode first=ptr.next;
ListNode second=first.next;
ListNode temp=second.next;
second.next=ptr.next;
ptr.next=ptr.next.next;
first.next=temp;
ptr=ptr.next.next;
}
return newhead.next;
}
}
要删除链表的倒数第n个结点,由于俩表没有下标,因此最简单的方法方法是直接遍历一遍链表将长度记录下来,然后再遍历一次。
但是有一种更加高效的方法,使用快慢指针的方法,先让快指针先出发,到第N个节点后,快慢指针同时前进,这样当快指针抵挡尾结点时,慢指针就恰好停留在倒数第N个结点上。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode newhead=new ListNode();
newhead.next=head;
ListNode slow=newhead;
ListNode fast=head;
while(fast!=null){
if(n==0){
slow=slow.next;
fast=fast.next;
}else{
fast=fast.next;
--n;
}
}
slow.next=slow.next.next;
return newhead.next;
}
}
直接先分别遍历两个链表并且记录各自的长度,然后记录他们的长度差gap,然后,长链表优先遍历,gap减为0后两链表同时遍历,各个结点进行比对。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lengthA=0;
int lengthB=0;
ListNode currA=headA;
ListNode currB=headB;
ListNode longer,shorter;
while(currA!=null){
currA=currA.next;
++lengthA;
}
while(currB!=null){
currB=currB.next;
++lengthB;
}
if(lengthA>=lengthB){
longer=headA;
shorter=headB;
}else{
longer=headB;
shorter=headA;
}
int gap=Math.abs(lengthA-lengthB);
while(gap-->0){
longer=longer.next;
}
while(longer!=null){
if(longer==shorter)
return longer;
longer=longer.next;
shorter=shorter.next;
}
return longer;
}
}
本题中,我的思路是:首先,先确认是否有环的存在
然后再是判断入口的位置。
要确认是否有环存在,可以使用快慢指针,快指针一定比慢指针先进入环,等到慢指针也进入环中时,此时便是追及问题,为了保证在追赶慢指针的时候避免出现刚好错开的情况,两指针的速度差应该为1。在确认有环后,再次启动快慢指针,第二次相遇时慢指针走2len,快指针走2len,得出环的长度
得出环的长度后,快慢指针回到起点且速度一致为1,这个时候快指针先出发走len长度,这时候慢指针启动,两指针同时移动,由于指针相隔len,因此必定会在环的起点(同时也是终点相遇,此时便可得出入口的下标)
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
/*
本题中,我的思路是:首先,先确认是否有环的存在
然后再是判断入口的位置。
要确认是否有环存在,可以使用快慢指针,快指针一定比慢指针先进入环,等到慢指针也进入环中时,此时便是追及问题,为了保证在追赶慢指针的时候避免出现刚好错开的情况,两指针的速度差应该为1。在确认有环后,再次启动快慢指针,第二次相遇时慢指针走2len,快指针走2len,得出环的长度
得出环的长度后,快慢指针回到起点且速度一致为1,这个时候快指针先出发走len长度,这时候慢指针启动,两指针同时移动,由于指针相隔len,因此必定会在环的起点(同时也是终点相遇,此时便可得出入口的下标)
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
boolean circle=false;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(slow==fast){
circle=true;
break;
}
}
if(!circle)
return null;
slow=slow.next;
fast=fast.next.next;
int len=1;
while(slow!=fast){
slow=slow.next;
fast=fast.next.next;
++len;
}
fast=head;
slow=head;
while(len>0){
fast=fast.next;
--len;
}
while(fast!=slow){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}