37-Sudoku Solver

題目描述:

https://leetcode.com/problems/sudoku-solver/

Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

  1. Each of the digits 1-9 must occur exactly once in each row.
  2. Each of the digits 1-9 must occur exactly once in each column.
  3. Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

Empty cells are indicated by the character '.'.


A sudoku puzzle...


...and its solution numbers marked in red.

Note:

  • The given board contain only digits 1-9 and the character '.'.
  • You may assume that the given Sudoku puzzle will have a single unique solution.
  • The given board size is always 9x9.

 

解答:

package com.jack.algorithm;

/**
 * create by jack 2019/6/30
 *
 * @author jack
 * @date: 2019/6/30 10:14
 * @Description:
 * 使用數字字符1-9填充二維數組
 */
public class SudokuSolver {

    /**
     * 37-題目描述:
     * https://leetcode.com/problems/sudoku-solver/
     *
     * @param board
     */
    public static void solveSudoku(char[][] board) {
        if (solve(board));
    }

    /**
     * 判斷某一行是否已經存在字符num,存在返回true,不存在返回false
     * @param board
     * @param row
     * @param num
     * @return
     */
    private static boolean usedRow(char[][] board, int row, char num) {
        //i小於二維數組的列數
        for (int i = 0; i < board[0].length; i++) {
            if (board[row][i] == num) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判斷num這個字符是否在這一列被使用了,被使用了返回true,沒被使用返回false
     * @param board
     * @param col
     * @param num
     * @return
     */
    private static boolean usedCol(char[][] board, int col, char num){
        for(int i=0; i<board.length; i++) {
            if (board[i][col] == num) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判斷3*3的單元格是否存在字符num,存在返回true,不存在返回false
     * @param board
     * @param rowStart
     * @param colStart
     * @param num
     * @return
     */
    private static boolean usedBox(char[][] board, int rowStart, int colStart, char num) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i + rowStart][j + colStart] == num) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * row行,collie填充字符num,是否安全
     * @param board
     * @param row
     * @param col
     * @param num
     * @return
     */
    private static boolean isSafe(char[][] board, int row, int col, char num) {
        //row-row%3用的比較巧妙,根據傳入的row找到第0,3,6行,這是3*3行的起始行
        //同理col-col%3,根據傳入的col找到0,3,6列,這是3*3行的起始列
        //所以根據上面的計算,可以找到所有的3*3的起始單元格
        return !usedRow(board, row, num) && !usedCol(board, col, num) && !usedBox(board, row - row % 3, col - col % 3, num) && board[row][col] == '.';
    }

    /**
     *查找到二維數組中有"."的列,並返回一個數組,數組兩個值,第一個值是i表示行,第二個值是j表示列
     * @param board
     * @return
     */
    private static int[] getUnfilledCell(char[][] board) {
        //二維數組行的長度
        for (int i = 0; i < board.length; i++) {
            //二維數組的列數
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] == '.') {
                    return new int[]{i, j};
                }
            }
        }
        return null;
    }

    /**
     * 遞歸調用填充,把“.”填充爲字符1-9
     * @param board
     * @return
     */
    private static boolean solve(char[][] board) {
        //獲取到沒有填充的單元格所在的行和列的數組,如果返回null表示已經填充完成了,直接返回ture
        int[] next = getUnfilledCell(board);
        if (next == null) {
            return true;
        }
        //獲取沒有填充列的行號,列號
        int row = next[0], col = next[1];
        //從ascill字符遍歷字符1-9字符
        for (char i = '1'; i <= '9'; i++) {
            //判斷填充字符i(i表示字符1-9),是否安全,如果安全,則把i賦值給row,col單元格
            if (isSafe(board, row, col, i)) {
                board[row][col] = i;
                //上面賦值了一個元素,繼續對第二個"."進行賦值,繼續遞歸調用,如果解決了就返回true,沒解決就重新把row,col單元格賦值爲"."
                if (solve(board)) {
                    return true;
                }
                board[row][col] = '.';
            }
        }
        return false;
    }

    public static void main(String[] args) {

    }
}

 

源碼:

源碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章