zoukankan      html  css  js  c++  java
  • 36. Valid Sudoku 终极之牛逼方法

    Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

    1. Each row must contain the digits 1-9 without repetition.
    2. Each column must contain the digits 1-9 without repetition.
    3. Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.

    The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

    Example 1:

    Input:
    [
      ["5","3",".",".","7",".",".",".","."],
      ["6",".",".","1","9","5",".",".","."],
      [".","9","8",".",".",".",".","6","."],
      ["8",".",".",".","6",".",".",".","3"],
      ["4",".",".","8",".","3",".",".","1"],
      ["7",".",".",".","2",".",".",".","6"],
      [".","6",".",".",".",".","2","8","."],
      [".",".",".","4","1","9",".",".","5"],
      [".",".",".",".","8",".",".","7","9"]
    ]
    Output: true
    

    Example 2:

    Input:
    [
      ["8","3",".",".","7",".",".",".","."],
      ["6",".",".","1","9","5",".",".","."],
      [".","9","8",".",".",".",".","6","."],
      ["8",".",".",".","6",".",".",".","3"],
      ["4",".",".","8",".","3",".",".","1"],
      ["7",".",".",".","2",".",".",".","6"],
      [".","6",".",".",".",".","2","8","."],
      [".",".",".","4","1","9",".",".","5"],
      [".",".",".",".","8",".",".","7","9"]
    ]
    Output: false
    Explanation: Same as Example 1, except with the 5 in the top left corner being 
        modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
    

    Note:

    • A Sudoku board (partially filled) could be valid but is not necessarily solvable.
    • Only the filled cells need to be validated according to the mentioned rules.
    • The given board contain only digits 1-9 and the character '.'.
    • The given board size is always 9x9.

    终极之无敌巧妙方法,理解不能

    class Solution {
    /*
      int rowIndex = 3 * (i / 3);
      int colIndex = 3 * (i % 3);
    i~[0,8]
    0 1 2 3 4 5 6 7 8
    0 0 0 3 3 3 6 6 6   row Index
    0 3 6 0 3 6 0 3 6   colIndex

    0 0 0 1 1 1 2 2 2   j / 3
    0 1 2 0 1 2 0 1 2   j % 3
    扫描cube时是从左到右从上到下扫描9个cube
    */
    public boolean isValidSudoku(char[][] board) { for(int i = 0; i < board.length; i++){ HashSet<Character> rows = new HashSet<>(); HashSet<Character> cols = new HashSet<>(); HashSet<Character> cube = new HashSet<>(); for(int j = 0; j < board[0].length; j++){ if(board[i][j] != '.' && !rows.add(board[i][j])) return false; if(board[j][i] != '.' && !cols.add(board[j][i])) return false; int rowIndex = 3 * (i / 3); int colIndex = 3 * (i % 3); if(board[rowIndex + j / 3][colIndex + j % 3] != '.' && !cube.add(board[rowIndex + j / 3][colIndex + j % 3])) return false; } } return true; } }

     好的 终于有一种看得懂的方法了,那就是遍历三次,检查三次

    class Solution {
    public boolean isValidSudoku(char[][] board) {
        //判断每一行
        for (int i = 0; i < 9; i++) {
            if (!isValidRows(board[i])) {
                return false;
            }
        }
        //判断每一列
        for (int i = 0; i < 9; i++) {
            if (!isValidCols(i, board)) {
                return false;
            }
        }
        //判断每个小棋盘
        for (int i = 0; i < 9; i = i + 3) {
            for (int j = 0; j < 9; j = j + 3) {
                if (!isValidSmall(i, j, board)) {
                    return false;
                }
            }
    
        }
        return true;
    }
    
    public boolean isValidRows(char[] board) {
        HashMap<Character, Integer> hashMap = new HashMap<>();
        for (char c : board) {
            if (c != '.') {
                if (hashMap.getOrDefault(c, 0) != 0) {//用getOrDefault是为了防止得到一个null(还不存在的element)
                    return false;
                } else {
                    hashMap.put(c, 1);
                }
            }
        }
        return true;
    }
    
    public boolean isValidCols(int col, char[][] board) {
        HashMap<Character, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < 9; i++) {
            char c = board[i][col];
            if (c != '.') {
                if (hashMap.getOrDefault(c, 0) != 0) {
                    return false;
                } else {
                    hashMap.put(c, 1);
                }
            }
        }
        return true;
    }
    
    public boolean isValidSmall(int row, int col, char[][] board) {
        HashMap<Character, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                char c = board[row + i][col + j];
                if (c != '.') {
                    if (hashMap.getOrDefault(c, 0) != 0) {
                        return false;
                    } else {
                        hashMap.put(c, 1);
                    }
                }
            }
        }
        return true;
    }
    
    }

     可不可以只遍历一次呢?可以,牛逼

    class Solution {
    public boolean isValidSudoku(char[][] board) {
        Set seen = new HashSet();
        for (int i=0; i<9; ++i) {
            for (int j=0; j<9; ++j) {
                char number = board[i][j];
                if (number != '.')
                    if (!seen.add(number + " in row " + i) ||
                        !seen.add(number + " in column " + j) ||
                        !seen.add(number + " in block " + i/3 + "-" + j/3))
                        return false;
            }
        }
        return true;
    }
    }
  • 相关阅读:
    vim讲解
    tar常用解包
    linux扩展权限
    为Virtualbox中的Solaris10安装VBoxAdditions
    Solaris10下Telnet、SSH、ftp使用root登录
    linux软链接和硬链接
    curl命令学习(转载的)
    linux磁盘分区fdisk命令详解
    在服务器上排除问题的头五分钟
    Java对文件压缩/加密/解密/解压缩的例子,DES/RSA
  • 原文地址:https://www.cnblogs.com/wentiliangkaihua/p/10332455.html
Copyright © 2011-2022 走看看