一、题目描述
二、解题思路
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
* 链表,双指针的题
* 题目的意思是什么?关键点是如何判断是有环
* 尾结点指向到了之前有的节点,需要对每一次的节点进行判断,是否已经存在过了。
* 那么这时候怎么区分这个节点就是原节点,而不是一个新的节点呢?通过内存地址来判断吗?
* 之思考的上面,下面是看题解写的
* 可以通过存储的内存地址来判断,通过 Map 来存储
* 击败了19.21%的用户
* 击败了5.00%的用户
*/
// var hasCycle = function(head) {
// let map = new Map();
// // 第一次错误,没有考虑到空链表的情况,[] -1,返回了undefined;
// if(!head) return false;
// while(head){
// if (map.has(head)) return true;
// map.set(head);
// head = head.next;
// if (head === null) return false;
// }
// };
/**
* 方案二,双指针方法,思想,两个人比赛赛跑,如果赛道是环形的,那么跑得快的一定会追上跑的慢的。
* 实现思路:构建两个指针,一个快,一个慢。当快的和慢的相等了,表示追上了。
* 追上的前提是,他们的距离在不断的拉大,相对距离不能一直保持一样,所以慢的每次跑一步,
* 快的每次跑两步,这样下去总能追上。
* 104 ms, 在所有 JavaScript 提交中击败了25.33%的用户
* 内存消耗:40.3 MB, 在所有 JavaScript 提交中击败了38.08%的用户
*/
var hasCycle = function(head) {
// 边缘情况考虑
if (!head || !head.next) return false;
let flow = head;
let fast = head.next;
while (fast !== null && fast.next) {// 判断走的快的是否已经到达了终点
if (flow === fast) return true;
flow = flow.next;
fast = fast.next.next;
if (fast === flow) {
return true;
}
}
return false;
}
总结:
两种方法,一种是通过哈希表进行存储,判断节点是否存在。 第二种方法,双指针,两个人在一个赛道上面跑步,如果赛道是环形赛道,跑得快的一定会追上跑得慢的。如果不是,跑的快的则会先到达终点。