1.翻转一个链表
:input a->b->c->d
:output d->c->b->a
// 链表翻转
const reverseList = function(head) {
let prev = null;
let curr = head;
while (curr) {
[ curr.next, prev, curr ] = [ prev, curr, curr.next ];
}
return prev;
};
let a = {
value:'a',next:null}
let b = {
value:'b',next:null}
let c = {
value:'c',next:null}
let d = {
value:'d',next:null}
a.next = b,b.next = c ,c.next =d;
reverseList(a)
2.翻转链表的m节点到n节点
:input a->b->c->d->e->f m=2,n=5
:output a-e->d->c->b->f
const reverseListBetween = function (head, m, n) {
let curr = head;
let prev = null;
for (let i = 1; i < m; ++i) {
[prev, curr] = [curr, curr.next];
}
let curr2 = curr;//第m个节点
let prev2 = prev;
//开始翻转
for (let i = m; i <= n; i++) {
[curr.next, prev, curr] = [prev, curr, curr.next]
}
//prev:第n个节点 ,curr是第N+1个
if (prev2) {
prev2.next = prev;
} else {
head = prev;
}
curr2.next = curr;
return head;
}
3.判断链表是否有环
利用快慢指针
const hasCycle = function (head) {
let fast = head;
let slow = head;
while (fast.next && fast.next.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
return true
}
}
return false;
}
4.如果有环,请返回环的入口
利用特性,fast指针走过的路程是slow指针的2倍
2slow = fast
假设head–>环入口的距离为a,环入口–>fast与slow相遇节点的距离为b,
此节点到环入口的节点距离为c(顺时针考虑)
根据两个指针各自走的路程 代入公式:2(a+b) = a + 2b+ c
=> a = c
表示在快慢指针相遇后,再走c步就能到环入口;从head开始走a步也能到环入口。
所以,在指针相遇后,slow指针继续走,再从头开始走一个新的slow指针,两者相遇时,就是环入口
const detectCycle = function (head) {
let fast = head;
let slow1 = head;
let slow2 = head;
let hasCycle = false;
while (fast.next && fast.next.next) {
fast = fast.next.next;
slow = slow.next;
if (fast === slow) {
hasCycle = true;
break;
}
}
if (!hasCycle)
return null;
while (slow1 !== slow2) {
slow1 = slow1.next;
slow2 = slow2.next;
}
return slow1;
}
以上内容 学习自b站JS老毕