leetcode之Valid Sudoku有效的数独(一步步改进代码)

题目链接:Valid Sudoku有效的数独

题目已经十分确定的说了只有1~9,因此标记法无疑是非常好的选择。

基本思路:对行、列、小数独块分别用一个size为9的数组来标记数字1~9在本行(列/块)中是否已使用。

根据思路则不难写出下面的代码:

	public static int startIndex = 0;
	public static int sudokuSize = 9;
	
    public boolean isValidSudoku(char[][] board) {
        int i;
        boolean[][] mark = new boolean[sudokuSize][sudokuSize+1];
        
        // 判断所有行是否符合
        for (i = startIndex; i < sudokuSize; i++) {
            for (int j = startIndex; j < sudokuSize; j++) {
            	if (board[i][j] != '.') {
            		int temp = board[i][j] - '0';
                    if (mark[i][temp]) return false;
                    else mark[i][temp] = true;
                }
            }
        }
        
        // 判断所有列是否符合
        initMarkArr(mark, false);
        for (i = startIndex; i < sudokuSize; i++) {
            for (int j = startIndex; j < sudokuSize; j++) {
                if (board[j][i] != '.') {
                    int temp = board[j][i] - '0';
                    if (mark[i][temp]) return false;
                    else mark[i][temp] = true;
                }
            }
        }
        
        // 判断所有小数独块是否符合
        initMarkArr(mark, false);
        for (i = startIndex; i < sudokuSize; i++) {
            for (int j = startIndex; j < sudokuSize; j++) {
            	int index = i/3 * 3 + j/3;
                if (board[j][i] != '.') {
                    int temp = board[j][i] - '0';
                    if (mark[index][temp]) return false;
                    else mark[index][temp] = true;
                }
            }
        }
        
        return true;
    }
    
    // 初始化数组
    public void initMarkArr(boolean[][] arr, boolean value) {
    	for (int j = 0; j < arr.length; j++) {
    		Arrays.fill(arr[j], value);
    	}
    }

代码看起来有点冗余,我们稍作代码简化,可得如下代码

    public boolean isValidSudoku(char[][] board) {
        boolean[][] markRow = new boolean[9][10];
        boolean[][] markCol = new boolean[9][10];
        boolean[][] markBlock = new boolean[9][10];
        // 多定义两个数组可以省去初始化操作
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int index = i/3 * 3 + j/3;
                if (board[j][i] != '.') {
                    int temp = board[j][i] - '0';
                    if (markRow[j][temp]) return false;
                    else markRow[j][temp] = true;
                    if (markCol[i][temp]) return false;
                    else markCol[i][temp] = true;
                    if (markBlock[index][temp]) return false;
                    else markBlock[index][temp] = true;
                }
            }
        }
        return true;
    }

对于此题,似乎没法靠优化算法来提升效率,硬要优化的话,可以在位运算上下点功夫。

    public boolean isValidSudoku(char[][] board) {
        int[][] mark = new int[3][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int index = i/3 * 3 + j/3;
                if (board[j][i] != '.') {
                    // 1左移?位,数独中最大数为9,2^8大大小于int的max
                    int temp = 1 << (board[j][i] - '1');
                    // 判断每列是否出现重复用temp,否则|上temp
                    if ((mark[0][j] & temp) > 0) return false;
                    else mark[0][j] |= temp;
                    // 每行
                    if ((mark[1][i] & temp) > 0) return false;
                    else mark[1][i] |= temp;
                    //每块
                    if ((mark[2][index] & temp) > 0) return false;
                    else mark[2][index] |= temp;
                }
            }
        }
        return true;
    }

进一步简化代码

    public boolean isValidSudoku(char[][] board) {
        int[][] mark = new int[3][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int index = i/3 * 3 + j/3;
                if (board[j][i] != '.') {
                    int temp = 1 << (board[j][i] - '1');
                    if ((mark[0][j] & temp) > 0 || (mark[1][i] & temp) > 0 || (mark[2][index] & temp) > 0) return false;
                    mark[0][j] |= temp;
                    mark[1][i] |= temp;
                    mark[2][index] |= temp;
                }
            }
        }
        return true;
    }

猜你喜欢

转载自blog.csdn.net/qq_36326947/article/details/80266062