Day4 leetcode 24,19,160,142

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. nextcur. 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]
思路:
由于是要找到倒数的节点,所以需要设置快慢两个指针,fastIndexslowIndex,当 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. 相交链表

题目:
给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
图示两个链表在节点 c1 开始相交**:**

题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
    思路:
    采用双指针的思路,让两个指针 cur 1,cur 2 分别指向两个链表的头节点,并一直向前移动,当运动到尾节点的时候,继续从另一个链表的头节点开始移动
    ![[Pasted image 20240930112108.png]]

如图,走到相交节点时,红线走了 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
思路:
三个问题,如何判断有没有环,快慢指针何时相遇,怎么判断相交的点。
定义快慢两个指针,fastIndexslowIndex,让 fastIndexslowIndex 两倍移动距离向前移动,也就是 fastIndex 每次移动两个节点,slowIndex 每次移动一个节点,如果没有环,那么 fastIndexslowIndex 永远不会相遇,只要有环就一定会相遇。
由于 fastIndex 是每次移动两个节点,slowIndex 是移动一个节点,fastIndex 一定是先进入环中,所以,当 slowIndex 进入环中的时候,其实是 fastIndex 不断地在追赶着 slowIndex,直到追赶上,所以,在两个指针没有相遇的时候,指针需要一直向前移动。但是又要保证进入了环,要确保指针 . next 的节点不为 null,并且记录相遇的时候的节点。
![[Pasted image 20240930161645.png]] 在这里插入图片描述

根据上图,可以确定,在 fastIndexslowIndex 相遇之后,从 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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值