【Lintcode】802. Sudoku Solver

题目地址:

https://www.lintcode.com/problem/sudoku-solver/description

解数独。

直接用DFS+回溯求解即可。代码如下:

import java.util.ArrayList;
import java.util.List;

public class Solution {
    /**
     * @param board: the sudoku puzzle
     * @return: nothing
     */
    public void solveSudoku(int[][] board) {
        // write your code here
        dfs(board, 0);
    }
    
    // 从start开始填数,如果填成功了则返回true
    private boolean dfs(int[][] board, int start) {
        int n = board.length;
        // 走到下一个需要填数的地方
        while (start < n * n && board[start / n][start % n] != 0) {
            start++;
        }
        // 如果走到末尾了,说明全填完了,返回true
        if (start == n * n) {
            return true;
        }
        // 求一下要填数的位置的坐标
        int x = start / n, y = start % n;
        // validNums求的是在board[x][y]这个地方允许填的数字
        for (int num : validNums(board, x, y)) {
        	// 尝试填
            board[x][y] = num;
           	// 如果填写成功,返回true
            if (dfs(board, start + 1)) {
                return true;
            }
            // 如果没成功,则恢复现场填下一个数
            board[x][y] = 0;
        }
        
        return false;
    }
    
    private List<Integer> validNums(int[][] board, int x, int y) {
        List<Integer> res = new ArrayList<>();
        
        for (int n = 1; n <= 9; n++) {
            boolean valid = true;
            for (int i = 0; i < board.length; i++) {
                if (i != y && board[x][i] == n) {
                    valid = false;
                    break;
                }
                if (i != x && board[i][y] == n) {
                    valid = false;
                    break;
                }
            }
            if (!valid) {
                continue;
            }
            
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    int c1 = x / 3 * 3, c2 = y / 3 * 3;
                    if (c1 + i != x && c2 + j != y && board[c1 + i][c2 + j] == n) {
                        valid = false;
                        break;
                    }
                }
                if (!valid) {
                    break;
                }
            }
            
            if (valid) {
                res.add(n);
            }
        }
        
        return res;
    }
}

时间复杂度 O ( 9 n ) O(9^n) ,空间 O ( n ) O(n) n n 为矩阵规模。

注意,回溯的时候一定要记得恢复现场,否则尝试下一个数字的时候会受到本不该填但已经填了的数的影响。

发布了354 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/104936637