You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } *//** * @param {ListNode} head * @param {number} n * @return {ListNode} */varremoveNthFromEnd=function(head,n){// first 和 second 分别表示第一个和第二个指针// last 表示指向 first 前一个节点的指针// 它在当需要删除的节点为最后一个节点时使用letlast=head,first=head,second=head;// 先移动第二个指针,与第一个指针错开 n - 1 个节点// 也就是让第二个指针和第一个指针之间的节点个数为 n - 1 个// 比如,假设 n = 2:// f// O - O - O - O - O - O -... - O - O// s// (last 总是指向 first 之前一个节点,故不展示)while(n--){second=second.next;}// 错开后,再同时移动 first 和 second 指针// 直到 second 指针指向 null,也就是最后一个节点的下一个节点(不存在这个节点,也就是 null)// 延续上例,此时:// f// O - O - O - O - O - O -... - O - O - null// s// 可以看出,此时 f 就是我们要删除的节点(倒数第 n=2 个节点)while(second){last=first;first=first.next;second=second.next;}// 剩下的就是对目标节点的边界判断了// 此时目标节点就是 first 指向的节点if(first===head){// 若目标节点时首节点head=first.next||null;// 首节点的下一个节点顶上作为新的首节点first.next=null;}elseif(first.next){// 若目标节点是非首非末节点first.val=first.next.val;first.next=first.next.next;}else{// 若目标节点是末节点(此时 last 派上用场)last.next=null;}returnhead;// 最后返回首节点};
思路:
思路见注释。
一次遍历,故时间复杂度 = O(1);
不占用额外空间,故空间复杂度 = O(1)。
这里解释一下:
虽然代码上用了两个循环,看起来是两次遍历,
但“一次遍历”是对链表长度而言的,
也就是说,如果一个循环并没有遍历完整个列表所有元素,那就不算“一次遍历”;
所以这里我们可以看到,
两个循环对链表遍历的总元素个数为 n + L - n = L,其中 L 为链表长度
也就是两个循环的实际效果是一次遍历,达到了题目的要求。
ARTS 第十九周(2019.8.5~2019.8.11)
Algorithm 删除链表的倒数第N个节点
题目:
删除链表的倒数第N个节点
代码
思路:
思路见注释。
一次遍历,故时间复杂度 = O(1);
不占用额外空间,故空间复杂度 = O(1)。
这里解释一下:
虽然代码上用了两个循环,看起来是两次遍历,
但“一次遍历”是对链表长度而言的,
也就是说,如果一个循环并没有遍历完整个列表所有元素,那就不算“一次遍历”;
所以这里我们可以看到,
两个循环对链表遍历的总元素个数为 n + L - n = L,其中 L 为链表长度
也就是两个循环的实际效果是一次遍历,达到了题目的要求。
对比:
与高分对比:
本代码运行 208 个测试用例花费约 68ms,平均一个测试用例约 0.33ms;
高分代码运行 208 个测试用例花费约 68ms,平均一个测试用例约 0.33ms。
思路一致代码略。
实际上我也是受到评论区的思路点拨才用的双指针,
不过这些思路还引入了“哑节点”,我觉得也可以不用就没有使用。
一开始我的思路是,题目要一次遍历是吧,那就把所有遍历过的节点缓存到一个 map,于是。。。
时间复杂度 O(1) 但空间复杂度 O(n)。
运行 208 个测试用例花费约 88ms,平均一个测试用例约 0.43ms;
Review 谷歌 JavaScript 代码风格规范的 13 个值得注意的要点
阅读:
13 Noteworthy Points from Google’s JavaScript Style Guide
点评:
文章对谷歌 JS 代码规范中的 13 个比较值得注意的条目进行了引用和点评:
Tab
);
)export
和import
)const
和let
彻底代替var
(为啥呢,见拓展阅读)this
产生任何影响+
)拼接多行字符串,而不是使用反斜杠(\
)来声明多行字符串(因为反斜杠兼容性不好)for-of
来遍历数组,对于 JSON 对象可以使用for-in
(for-of
的性能与for
相当,而且更美观)eval()
let a, b, c, ... = xxx
)'
)代替双引号("
),若单引号中还需要单引号,则外层使用反引号(```)对于代码规范,仁者见仁智者见智,除了 Google 规范,还有 Airbnb 规范,两套规范经常打架。
对于我们的项目,需参考已有大公司的实践,有针对性地摘取并在必要的时候扩展,以制定符合我们团队的代码规范。
拓展阅读:
Google JavaScript Style Guide
Why don’t we use var anymore?
Get around tslint: one-variable-per-declaration
Tip Nedb 在 JSON 对象数组的批量 $pull 上的问题
比如下面是一个例子,运行结果是:
Share [极客专栏] Git协同工作流,你该怎么选?
分享一篇极客“左耳听风”专栏文章(据说可限10位免费阅读哦)
20 | Git协同工作流,你该怎么选?
The text was updated successfully, but these errors were encountered: