背景😯
今天重刷 leetcode 的时候,刷到这么一道题102. 二叉树的层序遍历,很简单的二叉树遍历题目,三下五除二把代码写了出来
其他代码都不重要,重要的是第 27 行那里。
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var levelOrder = function(root) {
if(!root) return[]
const res = [],
que = [root, null]
let tmpLevel = []
while(que.length){
const t = que.shift()
if(t){
tmpLevel.push(t.val)
t.left && que.push(t.left)
t.right && que.push(t.right)
}else {// t为null
res.push(tmpLevel)
// tmpLevel.length = 0
tmpLevel = [] //第27行
que.length && que.push(null)
}
}
return res
};
const 和 let 的书写习惯
其他代码都不重要,重要的是第 27 行那里。我个人写代码的习惯时,能用const
就用const
,用了const
后面要修改时报错了再改为let
。
不知道你们是怎么呢
所以自然我的tmpLevel
一开始就是用const
定义,也就自然而然地在tmpLevel = []
处报错了。
改成let
定义后,也是自然而然地过了,但是我一下想起来,好像用tmp.length = 0
就能清空数组呀,还不用改const
~ 说不定性能还高一点? 真机(han)智(han) [doge]
数组清空的方式😏
splice
首先是 JavaScript 数组自身API:splice
arr.splice 方法可以说是处理数组的瑞士军刀。它可以做所有事情:添加,删除和插入元素。
语法:
arr.splice(start[, deleteCount, elem1,..., elemN])
它从索引 start 开始修改 arr:删除 deleteCount 个元素并在当前位置插入 elem1, …, elemN。最后返回已被删除元素的数组。
那直接从下标为 0,删掉数组长度那么长不就好了~
let arr = [1,2,3]
arr.splice(0,arr.length);
console.log(arr)//[]
arr.length
如果我们手动增加它,则不会发生任何有趣的事儿。但是如果我们减少它,数组就会被截断。该过程是不可逆的
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // 截断到只剩 2 个元素
console.log(arr); // [1, 2]
arr.length = 5; // 又把 length 加回来
console.log(arr[3]); // undefined:被截断的那些数值并没有回来
也就是说,我们直接将其赋值为0 就行
let arr = [1, 2, 3, 4, 5];
arr.length = 0
console.log(arr); // []
= []
直接将 arr 重新赋值为空数组,之前的数组如果没有被引用就等待垃圾回收就完事了~
三种方式的性能比较😎
我当时就想啊,算法题,肯定要追求一下效率的吗,上性能最好的干他~
测试
let a = [];
console.time('splice');
for(let i =0 ; i < 10;i++){
a = new Array(100).fill(111)
a.splice(0,a.length);
}
console.timeEnd('splice');
console.time('length');
for(let i =0 ; i < 10;i++){
a = new Array(100).fill(111)
a.length = 0;
}
console.timeEnd('length');
console.time('赋值[]');
for(let i =0 ; i < 10;i++){
a = new Array(100).fill(111)
a = [];
}
console.timeEnd('赋值[]')
一开始用了贼大的循环,直接卡死了🙃
结果
ok 那就是直接赋值性能最好, 直接修改 length
为0 性能其次,但是相差不多呀,用lenngth
还能保持我使用const
的习惯,那就上 第二种方法呗
结果😐
结果一看,不对劲啊,这清零怎么把最后结果的也给清了,猛地一下想到原因,直呼自己睿智
原因
其实这个我是知道的,但是写题的时候真就没想起来
注意 JS 数组重置的方式,虽然经测试arr.length = 0的速度会比arr = []快很多,但是这样是得不到正确答案的,原因是因为:
arr =[]创建的是一个新的数组,并为其赋予一个新的引用。其他引用不收影响,仍指向原数组
arr.length = 0修改数组本身,就算通过不同的变量访问它,得到的是同一个数组
直观测试
测试图解
也就是说 =[]
是创建了一个新数组,length=0
之后操作的仍是原来的引用~所以答案数组中的自然也就给一同清零了
总结🤔
唉这个东西,真是基础不牢地洞山摇啊~虽然是非常基础的知识点,但是可能到实际运用中就可能带来一些没料到的 bug 。
一开始测到性能差异,先入为主的就以为因为=[]
会创建一个新的引用吗~就会导致性能较差,导致性能测试结果都看歪来了😖也就导致自己”美滋滋地”用上不用改const
的方法…
不过有时这也说明,该用 let
时就用let
啊,不要头铁…
基础、基础,还是 的基础!