2020-04-07 (Array)
今天继续 Array。发现配合数组有很多属于 dp 的问题。
有一点心得,早上不适合刷题。晚上刷,脑子不好了,来一杯威士忌。
950. Reveal Cards In Increasing Order
早上上来第一题,我心态炸了,无能狂怒。如果面试遇到这道题,那也只能服了。一枪秒了,有什么好说的。 即使现在我对实现的思路还是很模糊,暂时先放一下,以后有思路了再来补充。
/**
* @param {number[]} deck
* @return {number[]}
*/
var deckRevealedIncreasing = function (deck) {
const sort = deck.sort((a, b) => a - b);
const queue = [];
for (let i = sort.length - 1; i >= 0; i--) {
if (queue.length) {
queue.push(queue.shift());
}
queue.push(sort[i]);
}
return queue.reverse();
};
1222. Queens That Can Attack the King
想法是从 king 的坐标开始,上下,左右,对角线, 四条线,八个方向上开始往外扩张。因为是找最邻近的,所以在该方向上命中一个就可以了,在那个方向就可以 return 了。一开始没注意这个 case,所以多了两个同行的解。还有一个点是两层循环生成 8 个向量。
/**
* @param {number[][]} queens
* @param {number[]} king
* @return {number[][]}
*/
var queensAttacktheKing = function (queens, king) {
const res = [];
const len = 8;
const [kx, ky] = king;
const set = new Set();
queens.forEach((q) => {
set.add(`${q[0]}${q[1]}`);
});
// 从 king 的坐标点开始,向八个方向蔓延, 每次 dx,增加 1
const traverse = function (x, y, dx, dy) {
// 如果当前 x,y 跑到棋盘外面就不再记录了
if (x < 0 || y < 0 || x > len - 1 || y > len - 1) { return; }
if (set.has(`${x}${y}`)) {
res.push([x, y]);
// 这里的 return 不能忘了,用来判断该方向上是否已经有了 queen,如果有了就跳出,不再继续往前走了。
return;
}
// 当前坐标加上向量值,移动到向量指向的新位置
traverse(x + dx, y + dy, dx, dy);
};
// 通过两层循环生成8个方向向量, 如[-1, 1],[0,1],[1,1],[1,0] 等等
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
// ignore [0, 0]
if (i === 0 && j === 0) continue;
// 起始点是 king 的 x,y 坐标
traverse(kx, ky, i, j);
}
}
return res;
};
1277. Count Square Submatrices with All Ones
看到这个二维数组找正方形,应该又是 dp。然后隐约记起一道题,一个机器人从左上走到右下,有多少种走法。加强版是路径中有些障碍,阻碍了一些道路。刚刚查了一下是 62,63。即是 Array 也是 DP。明天就他两了吧。我还想起 18 年面 Uber 的时候,也是一道类似的题目,一个人从左上走到右下,路上有一些钻石,不能走回头路,问能挖到的最大的钻石数目。也是异曲同工。本题没有生成一个新的 dp 数组去记录每个位置的正方形数量,而是直接 in-place 修改了 matrix。取决于题目需求,也可以开始的时候 slice 一个新的数组,这样不至于修改 input 元数据,但是会造成额外的 place。
/**
* @param {number[][]} matrix
* @return {number}
*/
var countSquares = function (matrix) {
const row = matrix.length;
const col = matrix[0].length;
let res = 0;
for (let i = 0; i < row; i++) {
for (let j = 0; j < col; j++) {
// 判断内层。加的那个1是最大的那个正方形
if (matrix[i][j] > 0 && i > 0 && j > 0) {
matrix[i][j] = Math.min(matrix[i - 1][j - 1], matrix[i - 1][j], matrix[i][j - 1]) + 1;
}
// 添加外层边上单独的 1
res += matrix[i][j];
}
}
return res;
};