1.环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null ){ //先判断是否是空表头
return null;
}
ListNode slow=head;
ListNode fast=head;
//使用两个指针,fast 与slow它们起始都位于链表的头部slow
//指针每次 向后移动一个位置,而fast 指针向后移动两个位置
while(fast!=null){
slow=slow.next;
if(fast.next !=null){
fast=fast.next.next;
}
else{
return null;
}
if(fast==slow){
//链表中存在环,则fast 指针最终将再次与 slow 指针在环中相遇
//当发现slow 与 fast 相遇时,我们再额外使用一个指针ptr。
//起始,它指向链表头部;随后,它和slow 每次向后移动一个位置。最终,它们会在入环点相遇。
ListNode ptr=head;
while(ptr !=slow){
ptr=ptr.next;
slow=slow.next;
}return ptr;
}
}
return null;
}
}
2.相交链表
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环
/**
* 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) {
if( headA==null || headB==null){
return null;
}
ListNode pA=headA,pB=headB;
while(pA!=pB){
pA=pA==null?headB:pA.next; //链表A循环结束就循环链表B
pB=pB==null?headA:pB.next; //链表A循环结束就循环链表B
//(3>2?"A":"B");//满足条件输出A,否则输出B
}
return pA;
}
}
3.删除链表的倒数第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 dummy=new ListNode(0,head);
//初始化一个空节点,初始赋值为0,并且list的下一个next指针指向head,指针指向为list
ListNode first=head;
ListNode second=dummy;
for(int i=0;i<n;++i){
first=first.next;
}
while(first !=null){
first=first.next;
second=second.next;
}
second.next=second.next.next;
ListNode ans=dummy.next;
return ans;
}
}
注意问题:
- 在调用 next 字段之前,始终检查节点是否为空。
获取空节点的下一个节点将导致空指针错误。例如,在我们运行 fast = fast.next.next 之前,需要检查 fast 和 fast.next 不为空。 - 仔细定义循环的结束条件。