LeetCode系列记录我学习算法的过程。
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情
题目
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例:
输入: head = [3,2,0,-4], pos = 1
输出: true
解释: 链表中有一个环,其尾部连接到第二个节点。
输入: head = [1,2], pos = 0
输出: true
解释: 链表中有一个环,其尾部连接到第一个节点。
输入: head = [1], pos = -1
输出: false
解释: 链表中没有环。
提示:
- 链表中节点的数目范围是
[0, 104] -105 <= Node.val <= 105pos为-1或者链表中的一个 有效索引 。
进阶: 你能用 O(1)(即,常量)内存解决此问题吗?
思路
又是链表题,求当前链表是否存在环形链表,及同一个节点被两个节点指向
那就很简单了,只要遍历一遍,将遍历过的节点打上标记,只要再遍历到标记的节点就说明存在环形链表:
- 首先定义指针变量进行遍历
- 如果当前节点的下一节点有被标记,则返回 true
- 反之则将当前节点打上标记,并将指针指向下一节点
- 全部遍历结束则返回 false
代码实现
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
// 定义变量遍历链表
let t = head
while(t?.next) {
// 如果下一个节点有被标记,返回 true
if(t.next?.flag) return true
// 反之标记当前结点,并移动到下一节点
t.flag = true
t = t.next
}
// 遍历结束则返回 false
return false
};
优化
题目给的进阶要求是不能对原链表进行操作,那这时就可以用双指针的思路来进行解答
通过双指针的快慢指针,慢指针每次走一步,快指针每次走两步,如果存在环形链表,那快慢指针一定会相遇:
var hasCycle = function(head) {
// 定义快慢指针
let slow = head, fast = head?.next
while(fast && fast?.next) {
// 快慢指针相遇返回 true
if(fast === slow) return true
// 慢指针走一步,快指针走两步
slow = slow.next
fast = fast.next?.next
}
// 遍历结束返回 false
return false
};