var isValidSudoku = function(board) {
// 初始化三个二维数组,分别记录行、列、九宫格中数字 1-9 的出现状态
// 长度为 9 对应 9 行/列/块,每个元素是一个长度为 10 的数组(方便直接用数字 1-9 作下标)
const rows = Array.from({ length: 9 }, () => Array(10).fill(false));
const cols = Array.from({ length: 9 }, () => Array(10).fill(false));
const subgrids = Array.from({ length: 9 }, () => Array(10).fill(false));
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
const char = board[i][j];
// 跳过空白格
if (char === '.') continue;
// 将字符转为数字
const num = parseInt(char);
// 计算当前坐标属于哪一个九宫格 (0-8)
const subgridIndex = Math.floor(i / 3) * 3 + Math.floor(j / 3);
// 检查是否在当前行、当前列或当前九宫格中出现过
if (rows[i][num] || cols[j][num] || subgrids[subgridIndex][num]) {
return false; // 只要有一条规则冲突,立即返回无效
}
// 记录当前数字已出现
rows[i][num] = true;
cols[j][num] = true;
subgrids[subgridIndex][num] = true;
}
}
return true; // 顺利遍历完说明全部合规
};
var spiralOrder = function(matrix) {
const result = [];
if (matrix.length === 0) return result;
let top = 0, bottom = matrix.length - 1;
let left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
// 从左到右遍历上边界
for (let j = left; j <= right; j++) {
result.push(matrix[top][j]);
}
top++;
// 从上到下遍历右边界
for (let i = top; i <= bottom; i++) {
result.push(matrix[i][right]);
}
right--;
// 从右到左遍历下边界(需要检查是否还有行)
if (top <= bottom) {
for (let j = right; j >= left; j--) {
result.push(matrix[bottom][j]);
}
bottom--;
}
// 从下到上遍历左边界(需要检查是否还有列)
if (left <= right) {
for (let i = bottom; i >= top; i--) {
result.push(matrix[i][left]);
}
left++;
}
}
return result;
};详细思路(边界收缩 + 计数终止)见 54 螺旋矩阵
var rotate = function(matrix) {
const n = matrix.length;
// 转置矩阵
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
[matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
}
}
// 水平翻转每行
for (let i = 0; i < n; i++) {
matrix[i].reverse();
}
};正确思路:用第一行和第一列作为标记数组,额外变量记录首行首列是否含0。
- 遍历矩阵,若
matrix[i][j] == 0,则标记matrix[i][0] = 0和matrix[0][j] = 0 - 根据标记将对应行列置0(注意避开首行首列)
- 最后处理首行首列
var setZeroes = function(matrix) {
const m = matrix.length, n = matrix[0].length;
let firstRowHasZero = false, firstColHasZero = false;
// 检查第一行是否有0
for (let j = 0; j < n; j++) {
if (matrix[0][j] === 0) {
firstRowHasZero = true;
break;
}
}
// 检查第一列是否有0
for (let i = 0; i < m; i++) {
if (matrix[i][0] === 0) {
firstColHasZero = true;
break;
}
}
// 用第一行和第一列作为标记
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (matrix[i][j] === 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// 根据标记置0(避开首行首列)
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (matrix[i][0] === 0 || matrix[0][j] === 0) {
matrix[i][j] = 0;
}
}
}
// 处理首行
if (firstRowHasZero) {
for (let j = 0; j < n; j++) {
matrix[0][j] = 0;
}
}
// 处理首列
if (firstColHasZero) {
for (let i = 0; i < m; i++) {
matrix[i][0] = 0;
}
}
};状态编码法:用额外数字记录转换态,原地更新不丢失信息。
| 编码 | 当前态 | 下一态 |
|---|---|---|
| 0 | 死 | 死 |
| 1 | 活 | 活 |
| 2 | 活 | 死 |
| 3 | 死 | 活 |
var gameOfLife = function(board) {
const m = board.length, n = board[0].length
const dirs = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]]
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
// 统计周围活细胞数(值为 1 或 2 表示当前活)
let live = 0
for (const [di, dj] of dirs) {
const r = i + di, c = j + dj
if (r >= 0 && r < m && c >= 0 && c < n &&
(board[r][c] === 1 || board[r][c] === 2)) {
live++
}
}
if (board[i][j] === 1) {
if (live < 2 || live > 3) board[i][j] = 2 // 活→死
} else {
if (live === 3) board[i][j] = 3 // 死→活
}
}
}
// 编码还原
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (board[i][j] === 2) board[i][j] = 0
else if (board[i][j] === 3) board[i][j] = 1
}
}
};