删除倒数第k个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
双指针:开始要在head的前一个,所以设置虚节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//快慢指针:快的先走k步,然后一起走
ListNode dummy=new ListNode(-1);
dummy.next=head;
ListNode fast=dummy;
ListNode slow=dummy;
ListNode pre=null;
while(n-->0){
fast=fast.next;
}
while(fast!=null){
fast=fast.next;
pre=slow;
slow=slow.next;
}
//删除
pre.next=slow.next;
//不能返回head,此时这里的head还是题目中给的引用,没有GC
return dummy.next;
}
}
链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
方法:
1:容器法
2:指针先走较长链法
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//用容器,使用map,把一A链表放入,在跌带B链表,迭代的时候看看表里有没有
HashSet<ListNode> set=new HashSet<>();
while(headA!=null){
set.add(headA);
headA=headA.next;
}
while(headB!=null){
if(set.contains(headB)) return headB;
headB=headB.next;
}
return null;
}
}
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//指针:相交后一定是相等的链长,先让长的链长走完长的,然后一起走
int countA=0;
int countB=0;
ListNode cur=headA;
while(cur!=null){
countA++;
cur=cur.next;
}
cur=headB;
while(cur!=null){
countB++;
cur=cur.next;
}
//让长的先走
int count=Math.abs(countA-countB);
ListNode headMax=countA>=countB?headA:headB;
ListNode headMin=countA>=countB?headB:headA;
while(count-->0){
headMax=headMax.next;
}
//一样长了
while(headMax!=null){
if(headMax==headMin) return headMax;
headMax=headMax.next;
headMin=headMin.next;
}
return null;
}
}
环链表问题
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
方法:
快慢指针法
public class Solution {
public ListNode detectCycle(ListNode head) {
//slow一步指针;fast两步指针
//如果有环,一定在环相遇:假设不相遇的上一步是相遇的,所以矛盾
//根据快慢指针的走过的结点数的2倍关系,推出,相遇后继续走和从头走,会在环口相遇
ListNode slow=head;
ListNode fast=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(slow==fast){//相遇了
slow=head;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return slow;
}
}
return null;//没有环
}
}