下面的基本上是我个人觉得比较适合陶冶情操、且不伤大脑的 leetcode 的脑筋急「卷」 弯。

这种题最好用 js 写(虽然我用的是 ts),心情和体验都会感到很好的(建议搭配 Quokka.js 插件食用)。

1. 两数相加

class ListNode {
    val,
    next,
    constructor(val, next) {
        this.val = (val === undefined ? 0 : val)
        this.next = (next === undefined ? null : next)
    }
}

/* 数字字符串 -> 链表 */
const iter = (numbers) => {
    const list = numbers.split('')
    return list.reduce((a, b) => a = new ListNode(BigInt(b), a), null)
}

/* 链表 -> 数字 */
const parser = (node) => {
    const list = []
    let temp = node
    while (temp !== null) {
        list.unshift(temp.val)
        temp = temp.next
    }
    return BigInt(list.join(''))  //BigInt 防止大数
}

/* 主函数 */
const addTwoNumbers = (l1, l2) => {
    return iter(String(parser(l1) + parser(l2)))
}

// 重点在于 iter & parser 函数的写法,挺简单的一道题

2. 三数之和

const threeSum = (nums) => {
    const list = nums.sort((a, b) => a - b)
    const result = []

		// 因为只有存在负数或者0的时候,才会三个数的和为0。而且i后面的指针最短为i + 2
    for (let i = 0; i < list.length - 2 && list[i] <= 0;i++) {
        if (i > 0 && list[i] === list[i - 1]) continue    // 防止重复元素重复计算
        let j = i + 1
        let z = list.length - 1
        while (j < z) {
            const sum = list[i] + list[j] + list[z]
            if (sum === 0) {
                result.push([list[i], list[j], list[z]])
                j++
                z--
								// 防止重复
                while (j < z && list[j] === list[j - 1]) {
                    j++
                }
                while (j < z && list[z] === list[z + 1]) {
                    z--
                }
            }else if (sum > 0) {
                z--
            }else if (sum < 0) {
                j++
            }
        }
    }
    return result
};

// 双指针老艺术了

3. 有效的数独

// 检查数组是否有效
const check = (list) => !list
    .map(e => e === '.' ? 0 : Number(e))   // ‘.‘ 转 0
    .sort((a, b) => a - b)                 // 排序,准备检查是否重复(非 0 的重复)
    .some((item, index, array) => index > 0 && item != 0 && item === array[index - 1])

const isValidSudoku = (board) => {
    for (let i = 0; i < 9; i++) {
        const column = []       //列
        const block = []        //每个 3 x 3 区块
        const row = board[i]    //行
        for (let j = 0; j < 9; j++) {
            column.push(board[j][i])
            block.push(board[
                Math.floor(i / 3) * 3 + (j % 3)
            ][
                (i % 3) * 3 + Math.floor(j / 3)
            ])
        }
        if (!check(row)) {
            return false
        }
        if (!check(column)) {
            return false
        }
        if (!check(block)) {
            return false
        }
    }
    return true
};

4. 生命游戏


const gameOfLife = (board: number[][]): void => {
    const _board = board.map(a => a.map(b => b))  // 深 拷 贝
    for (let i = 0; i < board.length; i++) {
        for (let j = 0; j < board[i].length; j++) {
            const list = [
                [taowa(_board, i - 1, j - 1), taowa(_board, i - 1, j), taowa(_board, i - 1, j + 1)],
                [taowa(_board, i, j - 1), _board[i][j], taowa(_board, i, j + 1)],
                [taowa(_board, i + 1, j - 1), taowa(_board, i + 1, j), taowa(_board, i + 1, j + 1)],
            ]
            board[i][j] = rush(list)
        }
    }
}

// 套娃:js 二维数组越界判断
const taowa = (board: number[][], row: number, column: number) => {
    try {
        return board[row][column] || 0
    } catch{
        return 0
    }
}

// 生命条件判断
const rush = (board: number[][]) => {
    let result = board[1][1]
    const alive = board
				.*reduce*((a, c) => a.concat(c), []) // 扁平化数组
				.reduce((acc, cur, idx) => idx != 4 ? acc + cur : acc) // 中心周围的数字累加

    if (alive < 2 && board[1][1] === 1) {
        result = 0
    }
    if ((alive === 2 || alive === 3) && board[1][1] === 1) {
        result = 1
    }
    if (alive > 3 && board[1][1] === 1) {
        result = 0
    }
    if (alive === 3 && board[1][1] === 0) {
        result = 1
    }
    return result
}