993. 二叉树的堂兄弟节点
BFS, 往往都需要根据问题自己定义一个数据结构 以后存入队列中,框架十分简单 取队列首部-do sth-弹出队首:就是while(q.length){ cur = q[0]; /*do sth*/ q.shift(); }
// https://leetcode-cn.com/problems/cousins-in-binary-tree/
const isCousins = function (root, x, y) {
let dx = -1, dy = -1, px = null, py = null;
let q = [];
q.push({
node: root,
pNode: null,
depth: 0,
});
while (q.length) {
let cur = q[0];
if (cur.node.val == x) {
dx = cur.depth
px = cur.pNode
};
if (cur.node.val == y) {
dy = cur.depth
py = cur.pNode
};
cur.node.left && q.push({
node: cur.node.left, pNode: cur.node, depth: cur.depth + 1
});
cur.node.right && q.push({
node: cur.node.right, pNode: cur.node, depth: cur.depth + 1
});
q.shift();
}
return dx == dy && px != py
};
其实JS语法特性可以让一些代码再简洁一些,看下题
剑指 Offer 13. 机器人的运动范围
const movingCount = function (m, n, k) {
const calcSum = (x, y) => (x + '' + y).split('').reduce((acc, cur) => +cur + acc, 0)
const dir = [[-1, 0], [1, 0], [0, -1], [0, 1]]
let vis = new Set(['0, 0']);
let q = [[0, 0]];
let res = 1;
while (q.length) {
let [i, j] = q.shift();
for (let d of dir) {
let x = i + d[0];
let y = j + d[1];
if (x < 0 || x >= m ||
y < 0 || y >= n ||
calcSum(x, y) > k ||
vis.has(x + ', ' + y)) {
continue;
}
res += 1;
vis.add(x + ', ' + y);
q.push([x, y]);
}
}
return res;
};
5. 最长回文子串
// https://leetcode-cn.com/problems/longest-palindromic-substring/
const longestPalindrome = function (s) {
if (s.length < 2) return s
let res = '';
for (let i = 0; i < s.length; i++) {
expand(s, i, i);
expand(s, i, i + 1);
}
function expand(s, i, j) {
while (s[i] == s[j] && i >= 0 && j < s.length) {
i--; j++;
}
j--; i++; // 注意,while里面多做了一次,要回退一下
let len = j - i + 1
if (len > res.length) res = s.slice(i, j + 1)
}
return res
};
56. 合并区间
// https://leetcode-cn.com/problems/merge-intervals/submissions/
const merge = (arr)=>{
arr.sort((a,b)=>a[0] - b[0])
let res = [arr[0]]
for (let curr of arr){
last = res[res.length - 1]
if(curr[0] > last[1]){
res.push(curr)
} else {
last[1] = Math.max(curr[1], last[1])
}
}
return res
}
1846. Maximum Element After Decreasing and Rearranging
关注的是"数组元素的取值" 若存在断层 则要全部下沉 届时顶端元素即为所求最大元素;
因为要求相邻元素不差过1,因此调整后取值最大不超过n,如果全部下沉压缩 空取值元素 以及重复的那些取值元素 会使顶端元素远小于n,
那么我们要使重复取值元素 分散到空取值处 填补断层,使下沉尽量少发生 顶端元素接近于n;
// https://leetcode-cn.com/problems/maximum-element-after-decreasing-and-rearranging/
const maximumElementAfterDecrementingAndRearranging = function(arr) {
const n = arr.length;
let count = new Array(n + 1).fill(0);
for(let num of arr){
count[Math.min(num, n)]++; // 所有大于n的都当做是n进行计数
}
let miss = 0;
for(let idx = 1; idx < n + 1; idx++) {
if (count[idx] == 0) { miss++; }
else if(count[idx] > 1) { // 可以分出一些元素填到miss的位置中
miss -= Math.min(miss, count[idx] - 1); // 自己也要留1个,占位越多 最后得到的最大值越大
}
}
return n - miss;
};
23. 合并K个升序链表
对于JS,用上reduce这个题相当于简单题了,转为合并2个游戏链表
// https://leetcode-cn.com/problems/merge-k-sorted-lists/
const mergeKLists = function (lists) {
if (!lists || !lists.length) { return null }
return lists.reduce(merge2Lists)
};
const merge2Lists = (a, b) => {
if (!a) return b;
if (!b) return a;
if (a.val < b.val) {
a.next = merge2Lists(a.next, b)
return a
} else {
b.next = merge2Lists(b.next, a)
return b
}
}