[Leetcode 37] stops alone

1. stops alone

Because I like to do Sudoku when young, so it is clear that Sudoku solving ideas, simply summarized as follows:

  1. First determine the possible values ​​for each space
  2. Fill in only one possible value spaces
  3. Update other colleagues, the same column, with 9 grids spaces possible values
  4. Repeat [2] [3], occurs in 3:
  • There is no space - problem-solving success
  • This problem no solution - either a space does not exist any possible values
  • The remaining space there are a number of possible values
  1. Try to assume the value of a space, repeat [2] [3] [4]

2. The algorithms and data structures

With problem-solving ideas, then we can design algorithms and data structures, and noted that the above-mentioned problem-solving process can be simplified to [qualify? Out of the line: re-queue], so consider a queue. Also note encounter step [5], it is necessary to set a hypothesis in the check value does not meet the requirements of the entire queue time, assuming the state before the launch back when no solution, then the next set of hypothetical values. A space with an index queue records remain to be solved, then a hash table values ​​may be recorded each space.

/**
 * deep clone
 */
var deepClone = function(obj) {
    if (typeof obj!=='object' || obj===null) {
        return obj;
    }
    let ret = Array.isArray(obj) ? [] : {};
    for (let k in obj) {
        ret[k] = deepClone(obj[k]);
    }
    return ret;
}

/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
var solveSudoku = function(board) {
    let _q = [],_hash = {}, allow = ['1','2','3','4','5','6','7','8','9'];
    // 初始化
    for (let i=0;i<9;i++) {
        for(let j=0;j<9;j++) {
            if (board[i][j] == '.') {
                // 初始化空格的所有可能值
                _hash[i*9+j] = Object.assign([], allow);
            } else {
                // 已填入的值
                _hash[i*9+j] = [board[i][j]];
            }
            _q.push(i*9+j);
        }
    }
    // 只有唯一解,否则会死循环
    function slove(q, hash) {
        while (q.length > 0) {
            let len = q.length;
            // 队尾删除避免索引混乱 (顺序好像也是可以的。。)
            for (let idx = len-1; idx >=0; idx--) {
                if (hash[q[idx]].length == 0) {
                    return false; // 无任何可能取值,本次无解
                }
                if (hash[q[idx]].length == 1) {
                    // 还原索引位置
                    let i = Math.floor(q[idx]/9), j = q[idx]%9;
                    board[i][j] = hash[q[idx]][0];
                    delete hash[q[idx]];
                    q.splice(idx,1);
                    // 删除关联位置的可能取值
                    for(let a in hash) {
                        let r = Math.floor(a/9), c = a%9;
                        if (r==i || c==j || (Math.floor(i/3)==Math.floor(r/3) && Math.floor(j/3)==Math.floor(c/3))){
                            // delete
                            let exist = hash[a].indexOf(board[i][j]);
                            if (exist !== -1) {
                                hash[a].splice(exist, 1);
                            }
                        }
                    }
                } else {
                    len--;  // 计数,
                }
            }
            // 出现多个位置多个可能取值,进入步骤【5】
            if(len == 0) {
                // 出现每个位置都有多个可能值,逐个假设尝试求解
                for (let n =0; n<hash[q[0]].length; n++) {
                    // 克隆状态,循环尝试求解
                    // 之前用了Object.assign()浅拷贝导致我调试了n久
                    let cloneHash = deepClone(hash);
                    let cloneQ = deepClone(q);
                    // 预先设定一个值
                    cloneHash[cloneQ[0]] = [hash[q[0]][n]];
                    if (slove(cloneQ, cloneHash)) {
                        return true;    // 解题成功,否则回溯进入下一个循环
                    }
                }
                // 所有可能值都失败,无解
                return false;
            }
        }
        return true;
    }
    slove(_q, _hash)
    return board;
};

3. Results and Optimization

执行用时 :104 ms, 在所有 JavaScript 提交中击败了63.07%的用户
内存消耗 :37.7 MB, 在所有 JavaScript 提交中击败了61.64%的用户

ac after a great God who went to see the solution to a problem, you can use the site to receive inspiration mark instead of an array of strings to optimize memory, which is to [1,2,3,4,5,6,7,8,9]replace a binary 11111111, for example, [1,5,6,8]can be expressed as 100011010the same token value can be changed to delete the position and operation:
Delete 5 :allow & 111101111

Guess you like

Origin www.cnblogs.com/dapianzi/p/12466141.html
37