虽然很多人都觉得前端算法弱,但其实 JavaScript 也可以刷题啊!最近两个月断断续续刷完了 leetcode 前 200 的 middle + hard ,总结了一些刷题常用的模板代码。
常用函数
包括打印函数和一些数学函数。
const _max = Math.max.bind(Math);
const _min = Math.min.bind(Math);
const _pow = Math.pow.bind(Math);
const _floor = Math.floor.bind(Math);
const _round = Math.round.bind(Math);
const _ceil = Math.ceil.bind(Math);
const log = console.log.bind(console);
//const log = _ => {}
log
在提交的代码中当然是用不到的,不过在调试时十分有用。但是当代码里面加了很多 log
的时候,提交时还需要一个个注释掉就相当麻烦了,只要将log
赋值为空函数就可以了。
举一个简单的例子,下面的代码是可以直接提交的。
// 计算 1+2+...+n
// const log = console.log.bind(console);
const log = _ => {
}
function sumOneToN(n) {
let sum = 0;
for (let i = 1; i <= n; i++) {
sum += i;
log(`i=${
i}: sum=${
sum}`);
}
return sum;
}
sumOneToN(10);
位运算的一些小技巧
判断一个整数 x
的奇偶性:x & 1 = 1 (奇数) , x & 1 = 0 (偶数)
求一个浮点数 x
的整数部分:~~x
,对于正数相当于 floor(x)
对于负数相当于 ceil(-x)
计算 2 ^ n
:1 << n
相当于 pow(2, n)
计算一个数 x
除以 2 的 n 倍:x >> n
相当于 ~~(x / pow(2, n))
判断一个数 x
是 2 的整数幂(即 x = 2 ^ n): x & (x - 1) = 0
※注意※:上面的位运算只对32位带符号的整数有效,如果使用的话,一定要注意数!据!范!围!
记住这些技巧的作用:
提升运行速度 ❌
提升逼格 ✅
举一个实用的例子,快速幂(原理自行google)
// 计算x^n n为整数
function qPow(x, n) {
let result = 1;
while (n) {
if (n & 1) result *= x; // 同 if(n%2)
x = x * x;
n >>= 1; // 同 n=floor(n/2)
}
return result;
}
链表
刚开始做 LeetCode 的题就遇到了很多链表的题。恶心心。最麻烦的不是写题,是调试啊!!于是总结了一些链表的辅助函数。
/** * 链表节点 * @param {*} val
* @param {ListNode} next
*/
function ListNode(val, next = null) {
this.val = val;
this.next = next;
}
/** * 将一个数组转为链表 * @param {array} a
* @return {ListNode} */
const getListFromArray = (a) => {
let dummy = new ListNode()
let pre = dummy;
a.forEach(x => pre = pre.next = new ListNode(x));
return dummy.next;
}
/** * 将一个链表转为数组 * @param {ListNode} node
* @return {array} */
const getArrayFromList = (node) => {
let a = [];
while (node) {
a.push(node.val);
node = node.next;
}
return a;
}
/** * 打印一个链表 * @param {ListNode} node */
const logList = (node) => {
let str = 'list: ';
while (node) {
str += node.val + '->';
node = node.next;
}
str += 'end';
log(str);
}
还有一个常用小技巧,每次写链表的操作,都要注意判断表头,如果创建一个空表头来进行操作会方便很多。
let dummy = new ListNode();
// 返回
return dummy.next;
使用起来超爽哒~举个例子。@leetcode 82。题意就是删除链表中连续相同值的节点。
参考视频:传送门
/** * @param {ListNode} head
* @return {ListNode} */
var deleteDuplicates = function(head) {
// 空指针或者只有一个节点不需要处理
if (head === null || head.next === null) return head;
let dummy = new ListNode();
let oldLinkCurrent = head;
let newLinkCurrent = dummy;
while (oldLinkCurrent) {
let next = oldLinkCurrent.next;
// 如果当前节点和下一个节点的值相同 就要一直向前直到出现不同的值
if (next && oldLinkCurrent.val === next.val) {