• 数独游戏底层算法


    数独游戏底层算法

    1. 填充数字以后判断是否是有效的数独
    2. bfs+回溯的暴利得到数独的解

    底层算法 对应leetcode的36,37题目

    1.有效的数独 见leetcode 36 力扣

    代码如下

    解题思想:使用行数组, 列数组,子箱子数组 记录指定位置元素出现的次数,数独游戏要求只能出现一次,故出现大于一次为false,如果9*9的方格都正确则为true.

    1. public class Test023 {
    2. //判断一个数独是否是一个合适的数独
    3. //题目地址: leetcode 36
    4. //https://leetcode.cn/problems/valid-sudoku/description/
    5. public static void main(String[] args) {
    6. char[][] board = {
    7. {'8', '3', '.', '.', '7', '.', '.', '.', '.'},
    8. {'6', '.', '.', '1', '9', '5', '.', '.', '.'},
    9. {'.', '9', '8', '.', '.', '.', '.', '6', '.'},
    10. {'8', '.', '.', '.', '6', '.', '.', '.', '3'},
    11. {'4', '.', '.', '8', '.', '3', '.', '.', '1'},
    12. {'7', '.', '.', '.', '2', '.', '.', '.', '6'},
    13. {'.', '6', '.', '.', '.', '.', '2', '8', '.'},
    14. {'.', '.', '.', '4', '1', '9', '.', '.', '5'},
    15. {'.', '.', '.', '.', '8', '.', '.', '7', '9'}
    16. };
    17. boolean flag = isValidSudoku(board);
    18. System.out.println("flag:" + flag);
    19. }
    20. public static boolean isValidSudoku(char[][] board) {
    21. // 行是9*9
    22. int[][] rows = new int[9][9];
    23. // 列是9*9
    24. int[][] cols = new int[9][9];
    25. // subBox是3*3*9
    26. int[][][] subBoxes = new int[3][3][9];
    27. for (int i = 0; i < board.length; i++) {
    28. for (int j = 0; j < board[0].length; j++) {
    29. if (board[i][j] != '.') {
    30. int index = board[i][j] - '0' - 1;
    31. rows[i][index]++;
    32. cols[j][index]++;
    33. subBoxes[i / 3][j / 3][index]++;
    34. if (rows[i][index] > 1 || cols[j][index] > 1 || subBoxes[i / 3][j / 3][index] > 1) {
    35. return false;
    36. }
    37. }
    38. }
    39. }
    40. return true;
    41. }
    42. }

    2.求数独的唯一解 见leetcode 37 力扣

    解题思路:dfs+回溯

    1.遍历9*9 把未填的空格加入列表

    2.依次遍历未填的列表 dfs+回溯

    注意:dfs函数有返回值,如果所有的未填的列表已经填完了,返回true

    1. public class Test024 {
    2. static boolean[][] rows = new boolean[9][9];
    3. static boolean[][] cols = new boolean[9][9];
    4. static boolean[][][] subBoxes = new boolean[3][3][9];
    5. static class Position {
    6. int x;
    7. int y;
    8. public Position(int x, int y) {
    9. this.x = x;
    10. this.y = y;
    11. }
    12. }
    13. public static void main(String[] args) {
    14. char[][] board = {{'5', '3', '.', '.', '7', '.', '.', '.', '.'},
    15. {'6', '.', '.', '1', '9', '5', '.', '.', '.'},
    16. {'.', '9', '8', '.', '.', '.', '.', '6', '.'},
    17. {'8', '.', '.', '.', '6', '.', '.', '.', '3'},
    18. {'4', '.', '.', '8', '.', '3', '.', '.', '1'},
    19. {'7', '.', '.', '.', '2', '.', '.', '.', '6'},
    20. {'.', '6', '.', '.', '.', '.', '2', '8', '.'},
    21. {'.', '.', '.', '4', '1', '9', '.', '.', '5'},
    22. {'.', '.', '.', '.', '8', '.', '.', '7', '9'}
    23. };
    24. solveSudoku(board);
    25. for (int i = 0; i < board.length; i++) {
    26. for (int j = 0; j < board[0].length; j++) {
    27. System.out.print(board[i][j] + " ");
    28. }
    29. System.out.println();
    30. }
    31. }
    32. public static void solveSudoku(char[][] board) {
    33. List list = new ArrayList<>();
    34. for (int i = 0; i < board.length; i++) {
    35. for (int j = 0; j < board[0].length; j++) {
    36. if (board[i][j] == '.') {
    37. list.add(new Position(i, j));
    38. } else {
    39. int index = board[i][j] - '0' - 1;
    40. rows[i][index] = true;
    41. cols[j][index] = true;
    42. subBoxes[i / 3][j / 3][index] = true;
    43. }
    44. }
    45. }
    46. solveSudokuHelper(board, list, 0);
    47. }
    48. //填充数独表格
    49. //函数为什么要有返回值
    50. public static boolean solveSudokuHelper(char[][] board, List list, int index) {
    51. if (index == list.size()) {
    52. return true;
    53. }
    54. Position position = list.get(index);
    55. for (char k = '1'; k <= '9'; k++) {
    56. boolean validSudoku = isValidSudoku2(board, position.x, position.y, k);
    57. if (validSudoku) {
    58. int index2 = k - '0' - 1;
    59. rows[position.x][index2] = true;
    60. cols[position.y][index2] = true;
    61. subBoxes[position.x / 3][position.y / 3][index2] = true;
    62. board[position.x][position.y] = k;
    63. boolean flag = solveSudokuHelper(board, list, index + 1);
    64. if (flag) {
    65. return true;
    66. }
    67. board[position.x][position.y] = '.';
    68. rows[position.x][index2] = false;
    69. cols[position.y][index2] = false;
    70. subBoxes[position.x / 3][position.y / 3][index2] = false;
    71. }
    72. }
    73. return false;
    74. }
    75. public static boolean isValidSudoku(char[][] board, int i, int j, char k) {
    76. //行检测
    77. for (int col = 0; col < 9; col++) {
    78. if (board[i][col] == k) {
    79. return false;
    80. }
    81. }
    82. //列检测
    83. for (int row = 0; row < 9; row++) {
    84. if (board[row][j] == k) {
    85. return false;
    86. }
    87. }
    88. //9宫格检测
    89. int startRow = (i / 3) * 3;
    90. int startCol = (j / 3) * 3;
    91. for (int p = startRow; p < startRow + 3; p++) {
    92. for (int q = startCol; q < startCol + 3; q++) {
    93. if (board[p][q] == k) {
    94. return false;
    95. }
    96. }
    97. }
    98. return true;
    99. }
    100. //isValidSudoku2比isValidSudoku时间复杂度低
    101. //isValidSudoku2 只需要比较3次,isValidSudoku需要比较27次
    102. //优化是否满足数独元素的判断
    103. //设置行,列,子盒子缓存,只需要3次判断就可确定是否是合格的数独
    104. public static boolean isValidSudoku2(char[][] board, int i, int j, char k) {
    105. //行检测
    106. int index = k - '0' - 1;
    107. if (!rows[i][index] && !cols[j][index] && !subBoxes[i / 3][j / 3][index]) {
    108. return true;
    109. }
    110. return false;
    111. }
    112. }

  • 相关阅读:
    获取dom元素
    记一次奇怪的SpringBoot多项目Mapper无法自动载入的错误
    C#基础总结二
    一种基于闭包函数实现自动化框架断言组件的设计实践
    资源描述框架的用途及实际应用解析
    SVM 超平面计算例题
    基于J2EE的在线网络考试系统的设计与实现
    如何看待Unity新的收费模式?
    测试开发基础 | Python 算法与数据结构面试题系列一(附答案)
    Java反射入门与反射执行Runtime示例
  • 原文地址:https://blog.csdn.net/u011243684/article/details/128173718