题目描述
问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个粗线宫内的数字均含1-9,并且不重复。
输入:
包含已知数字的9X9盘面数组[空缺位以数字0表示]
输出:
完整的9X9盘面数组
思路
这题在leetcode上见过,当时没有去解。直观上感受题目,最先想到的还是暴力遍历每种情况,但害怕时间复杂度会特别的高,所以迟迟不敢下手,今天实在是想不到了,就看了下别人的想法,发现还是深度遍历各种情况,草。
代码
import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class Main { private static int[][] m; public static void main(String...a){ Scanner in = new Scanner(System.in); while (in.hasNext()) { m = new int[9][9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { m[i][j] = in.nextInt(); } } helper(0, 0); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { System.out.print(m[i][j]); if (j < 8) System.out.print(' '); } System.out.println(); } } } private static Boolean helper(int x, int y){ /* 从二维数组的m[0][0]开始扫描第一行,当扫描到行尾时,转入扫描下一行。 扫描过的位置代表里边的数字符合规则,若能扫描到完最后一行,那么说明整个数独填补完了 当扫描到一个空位时,开始尝试填入数字,当所数字1-9都不能填补这个位置时,说明前面某个填的位置出现错误 */ if (x >= 9) return true; if (y >= 9) return helper(x+1, 0); if (m[x][y] != 0) return helper(x, y + 1); Set<Integer> existsNum = getExistsNum(x, y); for (int i = 1; i <= 9; i++) { if (existsNum.contains(i)) continue; m[x][y] = i; if (helper(x, y + 1)) { return true; } m[x][y] = 0; } return false; } private static Set<Integer> getExistsNum(int x, int y){ Set<Integer> set = new HashSet<>(); for (int i = 0; i < 9; i++) {//查看行和列出现过的数字 if (m[x][i] != 0) { set.add(m[x][i]); } if (m[i][y] != 0) { set.add(m[i][y]); } } int startX = x / 3 * 3, startY = y / 3 * 3; for (int i = 0; i < 3; i++) {//查看九宫格中出现过的数字 for (int j = 0; j < 3; j++) { if (m[startX + i][startY + j] != 0) { set.add(m[startX + i][startY + j]); } } } return set; } }