36. 有效的数独

 
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; // 顺利遍历完说明全部合规
};

54. 螺旋矩阵

 
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 螺旋矩阵

48. 旋转图像

 
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();
    }
};

73. 矩阵置零

正确思路:用第一行和第一列作为标记数组,额外变量记录首行首列是否含0。

  1. 遍历矩阵,若 matrix[i][j] == 0,则标记 matrix[i][0] = 0matrix[0][j] = 0
  2. 根据标记将对应行列置0(注意避开首行首列)
  3. 最后处理首行首列
 
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;
        }
    }
};

289. 生命游戏

状态编码法:用额外数字记录转换态,原地更新不丢失信息。

编码当前态下一态
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
        }
    }
};

相关笔记