24. 两两交换链表中的节点
题目:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入: head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入: head = []
输出:[]
示例 3:
输入: head = [1]
输出:[1]
思路:
首先要利用虚拟头节点来进行处理,因为要处理一个节点,必须要在他的前置节点才能处理。接着,判断循环的条件,假设为一个偶数链表,指针 cur
第一次指向的是 dummyhead
,它需要处理第一个节点和第二个节点交换,第二次要处理的是第三个节点和第四个节点的交换,所以他需要到达第二个节点,假设只有四个节点,那么再一次会指向第四个节点,这个时候就不需要再继续进行交换,所以 cur.next ===null
时候,就会停止交换。假设为一个奇数节点,同样是到第四个节点,后面还剩一个节点,但它不需要进行交换,此时 cur.next.next===null
,会停止。所以循环的判断条件是 while (cur.next!==null&&cur.next.next!==null)
,为什么这里要先写 cur. next
,因为如果先判断 cur. next. next!==null
的时候,加入 cur. next
已经等于 null
,就会有空指针导致循环错误。接着,进入循环,此时指针 cur
指向的是 dummyhead
,需要交换第一个节点和第二个节点的位置,所以需要将 cur. next
指向第二个节点,第二个节点的 next
指向第一个节点,但是如果先指向第二个节点,那么指向第一个节点的连接就会断开,导致找不到第一个节点,所以需要一个额外变量记住第一个节点,temp=cur. next
,此时 cur. next=cur. next. next
,cur. next. next = temp
,接着第一个节点会指向第三个节点,但由于第二个节点与第三个节点的连接断开,无法指向,所以需要在改变第二节点指向的时候同时储存第三个节点,temp 1=cur. next. next. next
,这个时候再让 cur. next. next. next=temp 1
即可,处理完这两个节点的问题,需要将 cur
向前移动两个位置,也就是 cur=cur. next. next
,接着循环结束,需要返回处理过后的链表的头节点,也就是虚拟头节点下一个指向,dummyhead. next
var swapPairs = function(head) {
let dummyhead = new ListNode(0,head)
let cur = dummyhead
while(cur.next !== null && cur.next.next !== null){
let temp = cur.next
let temp1 = cur.next.next.next
cur.next = cur.next.next
cur.next.next = temp
cur.next.next.next = temp1
cur = cur.next.next
}
return dummyhead.next
};
19. 删除链表的倒数第 N 个结点
题目:
给你一个链表,删除链表的倒数第 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]
思路:
由于是要找到倒数的节点,所以需要设置快慢两个指针,fastIndex
,slowIndex
,当 fastIndex到达尾节点的时候
,要求 slowIndex
处于需要删除节点的前一个节点。先考虑 slowIndex
到达需要删除节点的情况
![[Pasted image 20240930113315.png]]
当 fastIndex
到达 null
时候,如果两个指针中间差值为 n
,那么正好就能将 slowIndex
指向所需要删除的节点,所以,要得到前一个节点只需要让 fastIndex
先走一步即可。
var removeNthFromEnd = function(head, n) {
let dummyhead = new ListNode(0,head)
let fastIndex = dummyhead
let slowIndex = dummyhead
n++
while(n--){
fastIndex = fastIndex.next
}
while(fastIndex !== null){
fastIndex = fastIndex.next
slowIndex = slowIndex.next
}
slowIndex.next = slowIndex.next.next
return dummyhead.next
}
160. 相交链表
题目:
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
图示两个链表在节点 c1
开始相交**:**
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal
- 相交的起始节点的值。如果不存在相交节点,这一值为0
listA
- 第一个链表listB
- 第二个链表skipA
- 在listA
中(从头节点开始)跳到交叉节点的节点数skipB
- 在listB
中(从头节点开始)跳到交叉节点的节点数
思路:
采用双指针的思路,让两个指针 cur 1,cur 2 分别指向两个链表的头节点,并一直向前移动,当运动到尾节点的时候,继续从另一个链表的头节点开始移动
如图,走到相交节点时,红线走了 9
个节点,蓝线也走了 9
个节点,两个指针走的节点数是相同的,且他的下一个节点不是 null
,所以可以判断出只要相交,这样走距离一定相等,如果两个链表不相交,那么指针都会指向 null
。只要得到相等,就可以判断出交点是哪一个节点。
var getIntersectionNode = function(headA, headB) {
let cur1 = headA
let cur2 = headB
while(cur1 !== cur2){
cur1 = cur !== null ? cur1.next : headB
cur2 = cur !== null ? cur2.next : headA
}
return cur1
}
142. 环形链表 II
题目:
给定一个链表的头节点 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
思路:
三个问题,如何判断有没有环,快慢指针何时相遇,怎么判断相交的点。
定义快慢两个指针,fastIndex
,slowIndex
,让 fastIndex
以 slowIndex
两倍移动距离向前移动,也就是 fastIndex
每次移动两个节点,slowIndex
每次移动一个节点,如果没有环,那么 fastIndex
和 slowIndex
永远不会相遇,只要有环就一定会相遇。
由于 fastIndex
是每次移动两个节点,slowIndex
是移动一个节点,fastIndex
一定是先进入环中,所以,当 slowIndex
进入环中的时候,其实是 fastIndex
不断地在追赶着 slowIndex
,直到追赶上,所以,在两个指针没有相遇的时候,指针需要一直向前移动。但是又要保证进入了环,要确保指针 . next
的节点不为 null
,并且记录相遇的时候的节点。
![[Pasted image 20240930161645.png]]
根据上图,可以确定,在 fastIndex
和 slowIndex
相遇之后,从 head
到环入口和从相遇节点到环入口的距离是一样的,所以最后可以采用两个指针来重新表示,第一个指针指向相遇的节点,第二个指针指向 head
,直到两个指针相遇,可以确定当前的节点就是环入口。
var detectCycle = function(head) {
let fastIndex = head
let slowIndex = head
while(fastIndex !== null && fastIndex.next !== null){
fastIndex = fastIndex.next.next // fastIndex一定是走两个节点
slowIndex = slowIndex.next
if(fastIndex === slowIndex){
let index1 = fastIndex
let index2 = head
while(index1 !== index2){
index1 = index1.next
index2 = index2.next
}
return index1
}
}
return null
}