题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
视频讲解:https://www.bilibili.com/video/BV1YT411g7br/
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例2:
输入:head = []
输出:[]
示例3:
输入:head = [1]
输出:[1]
思路:先定义一个虚拟头结点,便于操作,1和2节点进行交换,如果直接将cur.next 指向cur.next.next,则会导致节点1丢失,节点3同理,因此在操作之前要将节点1和3提前保存。第二个关键点是循环结束的条件,题给条件是两两交换,当链表个数为偶数时,cur.next 为null时循环结束,当链表个数为奇数时,cur.next.nex为null时循环结束。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyhead = new ListNode();//定义虚拟头结点
dummyhead.next = head;// 将虚拟头结点指向head
ListNode cur = dummyhead;
ListNode temp;
ListNode temp1;
while(cur.next != null && cur.next.next != null){//循环结束条件
temp = cur.next;
temp1 = cur.next.next.next;//先将会丢失的元素保存
cur.next = cur.next.next;//步骤一
cur.next.next = temp;//步骤二
temp.next = temp1;//步骤三
cur = cur.next.next;//交换下一组元素
}
return dummyhead.next;
}
}
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
视频讲解:https://www.bilibili.com/video/BV1vW4y1U7Gf/
题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例2:
输入:head = [1], n = 1
输出:[]
示例3:
输入:head = [1,2], n = 1
输出:[1]
思路:首先是如何找到倒数第n个节点,先定义一个虚拟头结点(主要是便于我们对操作的元素是不是头结点不需要判断,可以采用统一的方法进行操作)。定义快慢指针,然后让快指针先移动n+1步,然后快慢指针再同时移动,直到快指针指向null,这时慢指针指向了要操作节点的前一个节点,就可以进行删除操作了。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyhead = new ListNode();//定义一个虚拟头结点
dummyhead.next = head;
ListNode fast = dummyhead;//快指针
ListNode slow = dummyhead;//慢指针
for(int i = 0; i < n + 1; i++){// 将快指针先移动n+1步,使慢指针指向要删除节点的前一个节点
fast = fast.next;
}
while(fast != null){//此时slow指向的是要删除节点的前一个节点
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummyhead.next;
}
}
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
(https://leetcode.cn/problems/intersection-of-two-linked-lists/)
题目描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
输入: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 。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0,lenB = 0;
while(curA != null){//求出链表A的长度
lenA++;
curA = curA.next;
}
while(curB != null){//求出链表B的长度
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
if(lenB > lenA){// 让curA为最长链表的头,lenA为其长度
int temp = lenA;
lenA = lenB;
lenB = temp;
ListNode tempNode = curA;
curA = curB;
curB = tempNode;
}
//求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while(gap-- > 0){
curA = curA.next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/
视频讲解:https://www.bilibili.com/video/BV1if4y1d7ob/
题目描述:给定一个链表的头节点 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
解释:链表中没有环。
思路:用快慢指针相遇来判断是否有环,使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
那么为什么fast指针和slow指针一定会相遇呢?这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。
详见Carl哥的代码随想录142.环形链表II
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(fast == slow){//有环
ListNode index1 = fast;//快慢指针相遇位置
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index2;
}
}
return null;
}
}
总结:今天的题对我来说有点难度,自己想根本想不出来,代码虽然看懂了,但是自己写还是不会,过几天再来看看,加强印象,这四天确实学到了很多东西,继续加油!