LeetCode解题笔记 7 —— 37.解数独

问题

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 '.' 表示。

一个数独。

答案被标成红色。

Note:

  • 给定的数独序列只包含数字 1-9 和字符 '.' 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

 

解法

class Solution {
    public void solveSudoku(char[][] board) {
//        board = new char[][]{
//                {'5', '3', '.', '.', '7', '.', '.', '.', '.'},
//                {'6', '.', '.', '1', '9', '5', '.', '.', '.'},
//                {'.', '9', '8', '.', '.', '.', '.', '6', '.'},
//                {'8', '.', '.', '.', '6', '.', '.', '.', '3'},
//                {'4', '.', '.', '8', '.', '3', '.', '.', '1'},
//                {'7', '.', '.', '.', '2', '.', '.', '.', '6'},
//                {'.', '6', '.', '.', '.', '.', '2', '8', '.'},
//                {'.', '.', '.', '4', '1', '9', '.', '.', '5'},
//                {'.', '.', '.', '.', '8', '.', '.', '7', '9'}
//        };
        board = get(board);
        for (char[] chars : board){
            StringBuilder builder  = new StringBuilder();
            for (char c : chars){
                builder.append(c).append(",");
            }
            System.out.println(builder.toString());
        }
    }

    public char[][] get(char[][] board){
        List<Set<Character>> vertical = new ArrayList<>();//列Set
        List<Set<Character>> horizontal = new ArrayList<>();//行Set
        List<List<Set<Character>>> nine = new ArrayList<>();//九宫格Set
        for(int i = 0; i< board.length; i++){
            vertical.add(new HashSet<Character>());
            horizontal.add(new HashSet<Character>());
            if (i%3==0){
                List<Set<Character>> l = new ArrayList<>();
                for (int j = 0; j<3; j++){
                    l.add(new HashSet<Character>());
                }
                nine.add(l);
            }
        }
        for(int i = 0; i< board.length; i++){
            for (int j = 0; j<board.length;j++){
                if (board[i][j]!='.'){
                    vertical.get(i).add(board[i][j]);
                    horizontal.get(j).add(board[i][j]);
                    nine.get(i/3).get(j/3).add(board[i][j]);
                }
            }
        }
        put(vertical, horizontal, nine,board);
        return  board;
    }

    public boolean put(List<Set<Character>> vertical, List<Set<Character>> horizontal, List<List<Set<Character>>> nine,char[][] board){
        int x = 0 ,y = 0;
        boolean flag = false;
        //找出未填的位置
        for (int i = 0; i< board.length; i++) {
            for (int j = 0; j< board.length; j++){
                if (board[i][j]=='.'){
                   x = i;
                   y = j;
                   flag = true;
                }
            }
        }
        if (flag){
            char c = '0';
            for (int z = 0;z<9;z++){
                c++;
                if (!vertical.get(x).contains(c) && !horizontal.get(y).contains(c) && !nine.get(x/3).get(y/3).contains(c)){
                    vertical.get(x).add(c);
                    horizontal.get(y).add(c);
                    nine.get(x/3).get(y/3).add(c);
                    board[x][y] = c;
                    if (put(vertical, horizontal, nine,board)){
                        return true;
                    }else {
                        vertical.get(x).remove(c);
                        horizontal.get(y).remove(c);
                        nine.get(x/3).get(y/3).remove(c);
                        board[x][y] = '.';
                    }
                }
            }
            return false;
        }
        return true;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值