zoukankan      html  css  js  c++  java
  • Leetcode: Sudoku Solver

    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.

    又是一道NP的问题,这种问题时间复杂度就不用考虑了,肯定是指数量级的,参考了一下别人的思路,这道题的思路与N-Queens,Permutations问题比较相似, 简单地说思路就是循环处理子问题,对于每个格子,带入不同的9个数,然后判合法,如果成立就递归继续。判合法可以用Valid Sudoku做为subroutine,但是其实在这里因为每次进入时已经保证之前的board不会冲突,所以不需要判断整个盘,只需要看当前加入的数字和之前是否冲突就可以,这样可以大大提高运行效率,毕竟判合法在程序中被多次调用。

    第二遍做法:

     1 public class Solution {
     2     public void solveSudoku(char[][] board) {
     3         if (board == null || board.length != 9 || board[0].length != 9) return;
     4         helper(board, 0, 0);
     5     }
     6     
     7     public boolean helper(char[][] board, int i, int j) {
     8         if (j == 9) return helper(board, i+1, 0);
     9         if (i == 9) return true;
    10         if (board[i][j] != '.') return helper(board, i, j+1);
    11         for (int k=0; k<9; k++) {
    12             board[i][j] = (char)('1' + k);
    13             if (check(board, i, j)) {
    14                 if (helper(board, i, j+1)) return true;
    15             }
    16         }
    17         board[i][j] = '.';
    18         return false;
    19     }
    20     
    21     public boolean check(char[][] board, int i, int j) {
    22         for (int t=0; t<9; t++) {
    23             if (t != i && board[t][j] == board[i][j]) return false;
    24         }
    25         for (int t=0; t<9; t++) {
    26             if (t != j && board[i][t] == board[i][j]) return false; 
    27         }
    28         for (int s=i/3*3; s<i/3*3+3; s++) {
    29             for (int t=j/3*3; t<j/3*3+3; t++) {
    30                 if (s!=i || t!=j) {
    31                     if(board[s][t] == board[i][j]) return false;
    32                 }
    33             }
    34         }
    35         return true;
    36     }
    37 }

    17行一定要记得在return false之前把board[i][j] 改回‘.’, 否则会出很严重的错误:比如board[i][j+1]把1~9都试过都不是valid的,这时候要回到board[i][j]去换另一个数试一试,再进入board[i][j+1],由于刚才已经把它改成1~9了而且没有改回‘.’,所以递归就会沿着一条错误的路走下去。最后会得到一组明显错误的答案(里面很多重复)

     1 public class Solution {
     2     public void solveSudoku(char[][] board) {
     3         if (board == null || board.length != 9 || board[0].length != 9) return;
     4         helper(board, 0, 0);
     5     }
     6     
     7     public boolean helper(char[][] board, int i, int j) {
     8         if (j >= 9) return helper(board, i+1, 0);
     9         if (i >= 9) return true;
    10         if (board[i][j] == '.') {
    11             for (int k = 1; k <= 9; k++) {
    12                 board[i][j] = (char)('0' + k);
    13                 if (isvalid(board, i, j)) {
    14                     if(helper(board, i, j+1))
    15                     return true;
    16                 }
    17                 board[i][j] = '.';
    18             }
    19         }
    20         else {
    21             return helper(board, i, j+1);
    22         }
    23         return false;
    24     }
    25     
    26     public boolean isvalid(char[][] board, int i, int j) {
    27         for (int a = 0; a < 9; a++) {
    28             if (a != i && board[a][j] == board[i][j]) return false;
    29         }
    30         
    31         for (int b = 0; b < 9; b++) {
    32             if (b != j && board[i][b] == board[i][j]) return false; 
    33         }
    34         
    35         for (int c = i/3*3; c < i/3*3 + 3; c++) {
    36             for (int d = j/3*3; d < j/3*3 + 3; d++) {
    37                 if ((c != i || d != j) && board[c][d] == board[i][j]) return false;
    38             }
    39         }
    40         
    41         return true;
    42     }
    43 }

    在具体编程的时候,还有一个细节问题需要注意,那就是37行 (c != i || d != j)这个操作一定要用括号括起来,否则&&的操作优先级比||高,会出错

  • 相关阅读:
    iOS开发之集成iOS9中的Core Spotlight Framework搜索App的内容
    Masonry介绍与使用实践(快速上手Autolayout)(转)
    NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象(转)
    UIViewController 中的 willMoveToParentViewController和didMoveToParentViewController的使用(转载)
    iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译
    iOS在UITableView全面解析
    iOS UILabel详解(转载)
    UIScrollViewDelegate-委托方法API
    wordpress通过代码禁用IE8, IE9,IE10等IE浏览器兼容视图模式(Compatibility View)
    LNMP安装WordPress3.4.2看不到主题解决方法
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/3965583.html
Copyright © 2011-2022 走看看