给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
可以设置虚拟头结点cur和画图来方便理清逻辑。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode v=new ListNode(0);//虚拟头结点
v.next=head;//虚拟头结点指向头结点
ListNode cur=v;
while(cur.next!=null&&cur.next.next!=null){
//提前保存节点
ListNode tmp=cur.next;
ListNode tmp1=cur.next.next.next;
cur.next=cur.next.next;//步骤一
cur.next.next=tmp;//步骤二
cur.next.next.next=tmp1;//步骤三
cur=cur.next.next;//cur前进,进行下一轮
}
return v.next;
}
}
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
本题可以使用双指针法,快指针首先前进n次,随后快慢指针一起前进,当快指针到达末尾时,慢指针到达目标节点的前一个节点。
就拿上图举例,快指针前进2次,随后快慢指针一起前进,当快指针到达5,慢指针到达3.
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode v=new ListNode(0);//虚拟头结点
v.next=head;
ListNode fast=v;//快指针
ListNode slow=v;//慢指针
for(;n>0;n--)fast=fast.next;//快指针首先前进n次
while(fast.next!=null){
//慢指针一起前进
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;//删除节点
return v.next;
}
}
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交**:**
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。
提示:
listA
中节点数目为 m
listB
中节点数目为 n
0 <= m, n <= 3 * 104
1 <= Node.val <= 105
0 <= skipA <= m
0 <= skipB <= n
listA
和 listB
没有交点,intersectVal
为 0
listA
和 listB
有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]
本题的关键在于如何让两个指针不会错开,例如一个指针已经到公共链表,另一个还没到,这样就无法判断了。
因此可以利用两个链表的长度差让两个指针初始位置在公共节点前的相同位置,链表A长,就先移动指针a,链表B长,就先移动指针b。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a=headA;
ListNode b=headB;
int lena=0;
int lenb=0;
//获取链表长度
while(a!=null){
a=a.next;
lena++;
}
while(b!=null){
b=b.next;
lenb++;
}
a=headA;
b=headB;
//移动指针使两者位于相同初始位置
if(lena>lenb)for(int i=0;i<lena-lenb;i++)a=a.next;
else for(int i=0;i<lenb-lena;i++)b=b.next;
//移动指针使其指向公共节点
while(a!=null){
if(a==b)return a;
a=a.next;
b=b.next;
}
return null;
}
}
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
提示:
[0, 104]
内-105 <= Node.val <= 105
pos
的值为 -1
或者链表中的一个有效索引本题可使用双指针法,若链表内存在环,则快慢指针一定会相遇。相遇后再从头结点出发一个慢指针,则该指针将与原先的慢指针相遇。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){//判断是否有环
fast=fast.next.next;//快指针移动
slow=slow.next;//慢指针移动
if(slow==fast){//有环
fast=head;//从头结点出发一个慢指针(快指针重复利用)
while(true){
if(slow==fast)return slow;//相遇
slow=slow.next;//原先的慢指针
fast=fast.next;//新设的慢指针
}
}
}
return null;
}
}