Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the character '.'. You may assume that there will be only one unique solution.
也就是給出一個解決數獨的方法,假設每一個數獨只有一個解決方案。c++
不使用數據結構意味着咱們本身在每一次遇到一個空格時,須要在board中對該空格所在的行,列以及方塊進行遍歷,判斷填入什麼數字是合適的。並將當前的假象結果帶入下一輪的遍歷之中。若是最終遍歷失敗,則逐級返回,恢復上一輪遍歷的狀態,並填入下一個合理的假想值後繼續遍歷。這裏涉及的時間複雜度是很高的,畢竟只是遍歷整個board就須要O(n^2),若是遇到一個空格還須要O(n)來判斷填入值是否合理。總共O(n^3)的時間複雜度。代碼以下:面試
public void solveSudoku(char[][] board) { if(board == null || board.length == 0) return; solve(board); } public boolean solve(char[][] board){ for(int i = 0; i < board.length; i++){ for(int j = 0; j < board[0].length; j++){ if(board[i][j] == '.'){ for(char c = '1'; c <= '9'; c++){//trial. Try 1 through 9 if(isValid(board, i, j, c)){ board[i][j] = c; //Put c for this cell if(solve(board)) return true; //If it's the solution return true else board[i][j] = '.'; //Otherwise go back } } return false; } } } return true; } //橫 豎 方塊 private boolean isValid(char[][] board, int row, int col, char c){ for(int i = 0; i < 9; i++) { if(board[i][col] != '.' && board[i][col] == c) return false; //check row if(board[row][i] != '.' && board[row][i] == c) return false; //check column if(board[3 * (row / 3) + i / 3][ 3 * (col / 3) + i % 3] != '.' && board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == c) return false; //check 3*3 block } return true; }
咱們使用boolean[][] rows, boolean[][] columns, boolean[][] squares
分別記錄行列和方塊的全部值狀況。其中rowsi記錄i行是否有值j,columnsi記錄i列是否有值j,squaresi記錄第i個方塊是否有值j。整體思路仍是和上一個差很少,只是經過消費了存儲空間的基礎上提升了性能。數組
public void solveSudoku2(char[][] board) { int length = board.length; //記錄第i行是否出現j數字 boolean[][] rows = new boolean[length][length+1]; //第i列是否出現j數字 boolean[][] columns = new boolean[length][length+1]; //第i個小方格是否出現j數字。 boolean[][] squares = new boolean[length][length+1]; for(int i = 0 ; i < length ; i++){ for(int j = 0 ; j<length ; j++){ if(board[i][j] != '.'){ int value = board[i][j] - '0'; rows[i][value] = true; columns[j][value] = true; squares[i / 3 * 3 + j / 3][value] = true; } } } solveSudoku(board, 0, rows, columns, squares); } private boolean solveSudoku(char[][] board, int index, boolean[][] rows, boolean[][] columns, boolean[][] squares){ if(index == 81){ return true; } int row = index / 9; int column = index % 9; int square = row/3*3 + column/3; if(board[row][column]=='.'){ for(char i = '1' ; i<='9' ; i++){ if(rows[row][i-'0'] || columns[i-'0'][column] || squares[square][i-'0']) continue; board[row][column] = i; rows[row][i-'0'] = true; columns[column][i-'0'] = true; squares[square][i-'0'] = true; if(solveSudoku(board, index+1, rows, columns, squares)){ return true; }else{ board[row][column] = '.'; rows[row][i-'0'] = false; columns[column][i-'0'] = false; squares[square][i-'0'] = false; } } return false; } return solveSudoku(board, index+1, rows, columns, squares); }
看到一個解答 效率很高 可是不是很明白 但願看到的大神解答一下微信
private boolean solver(int idx, char[][] board, ArrayList<Integer> stack, int[] store) { if (idx == stack.size()) return true; int n = stack.get(idx); int y = n / 9; int x = n - y * 9; int h = y; int v = 9 + x; int b = 18 + (y / 3 * 3 + x / 3); int available = ~store[h] & ~store[v] & ~store[b] & 0b111111111; while (available > 0) { int bit = available & -available; int num = Integer.numberOfTrailingZeros(bit); store[h] ^= bit; store[v] ^= bit; store[b] ^= bit; board[y][x] = (char)(num + '1'); if (solver(idx + 1, board, stack, store)) return true; store[h] ^= bit; store[v] ^= bit; store[b] ^= bit; // board[y][x] = '.'; available &= available - 1; } return false; } public void solveSudoku3(char[][] board) { ArrayList<Integer> stack = new ArrayList<>(); // int[] stack = new int[81]; int len = 0; int[] store = new int[27]; // 0-8 h, 9 - 17 v, 18 - 26 b for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] == '.') stack.add(i * 9 + j); else { int h = i; int v = 9 + j; int b = 18 + (i / 3 * 3 + j / 3); store[h] ^= 1 << board[i][j] - '1'; store[v] ^= 1 << board[i][j] - '1'; store[b] ^= 1 << board[i][j] - '1'; } } } solver(0, board, stack, store); }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~數據結構