这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
101. 反转链表 (reverse-linked-list)
标签
- 链表
- 简单
题目
这里不贴题了,leetcode打开就行,题目大意:
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
基本步骤
初始的样子大概长这样
null [1|]-> [2|] -> [3|] -> null
|(1) |(2) |(3)
prev cur cur.next
其实我们就看成3步
- (3) 指向 (1)
- (1) (2) 往后移一位
- 直到 cur 到 null 那么 prev 就是链表头了,返回就行
写法实现
这个简单的写法实现建议搞懂后作为一个记忆模块。
var reverseList = function(head) {
let [cur, prev] = [head, null];
while (cur) {
[cur.next, prev, cur] = [prev, cur, cur.next]
}
return prev
};
102. 环形链表 (linked-list-cycle)
标签
- 链表
- 简单
题目
这里不贴题了,leetcode打开就行,题目大意:
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递
,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
基本思想
思路1: 标记
每次走的过程中,用一个 Set
或者数组(Array) 记录下访问过的节点地址,如果有环存在,总会遇到重复节点,当走到的节点落在 Set 中,就说明有环存在。O(n)的时间复杂度
思路2: 快慢指针
设置快慢指针,快指针每次两步,慢指针每次一步,如果有环存在,在某轮总有快指针追上慢指针。O(n)的时间复杂度,也不需要额外的空间 O(1) 即常量内存
写法实现
标记
const hasCycle = function(head) {
const res = [];
let cur = head;
while (cur) {
if (res.includes(cur)) {
return true;
}
res.push(cur);
cur = cur.next;
}
return false;
};
快慢指针
var hasCycle = function(head) {
let [slow, fast] = [head, head]
// 快慢指针走到头都没发现有环,就 return false
while(slow && fast && fast.next) {
// 快指针每次走两步,慢指针每次一步
fast = fast.next.next
slow = slow.next
// 如果追上,就说明有环
if (fast === slow) {
return true
}
}
return false
};
疑问: 为什么追上是 fast === slow
有没正好超过而不汇合的情况呢?
其实是没有的,一个一次一步,一个一次两步,你画图就明白了,如果快指针在慢指针后方,diff == 1
那么下次就会重合。diff == 2
那么再走一步就变成 diff == 1
,注意你在纸上画个图马上就明白,我不帮你画,自己动手印象深。
另外用 set 增加额外空间来判重的方式就不实现了,相对来说也比较简单。
另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧