题解 | #Sudoku#
Sudoku
https://www.nowcoder.com/practice/78a1a4ebe8a34c93aac006c44f6bf8a1
空间换时间,时间复杂度不会算,它取决于没有填数字的空格数,但应该是最小的了。
分别用3个map记录第x行、第y列、第x行第y列所在小九宫格是否存在val值。
输入数据时,专门用一个队列来存储没有填数字的空格,后续使用回溯算法的主要对象就是这个队列,这样可以大大减少时间复杂度。
import java.util.Scanner; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; public class Main { private static boolean[][] rowMap = new boolean[9][9]; private static boolean[][] colMap = new boolean[9][9]; private static boolean[][] squareMap = new boolean[9][9]; private static Map<String, Integer> squareIdxMap = new HashMap<>(); public static void main(String[] args) { initSquareIdxMap(); Scanner in = new Scanner(System.in); int[][] nums = new int[9][9]; LinkedList<Pos> zeroQueue = new LinkedList<>(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { nums[i][j] = in.nextInt(); if (nums[i][j] == 0) { zeroQueue.offer(new Pos(i, j)); } else { rowMap[i][nums[i][j] - 1] = true; colMap[j][nums[i][j] - 1] = true; squareMap[getSquareI(i, j)][nums[i][j] - 1] = true; } } } traceBack(nums, zeroQueue); } private static void initSquareIdxMap() { int idx = 0; squareIdxMap.put("1,1", idx++); squareIdxMap.put("1,4", idx++); squareIdxMap.put("1,7", idx++); squareIdxMap.put("4,1", idx++); squareIdxMap.put("4,4", idx++); squareIdxMap.put("4,7", idx++); squareIdxMap.put("7,1", idx++); squareIdxMap.put("7,4", idx++); squareIdxMap.put("7,7", idx++); } private static Integer getSquareI(int x, int y) { String key = (3 * (x / 3) + 1) + "," + (3 * (y / 3) + 1); return squareIdxMap.get(key); } private static void printNums(int[][] nums) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { System.out.print(nums[i][j] + " "); } System.out.println(); } } private static boolean traceBack(int[][] nums, LinkedList<Pos> zeroQueue) { if (zeroQueue.isEmpty()) { printNums(nums); return true; } boolean result = false; Pos curPos = zeroQueue.poll(); for (int k = 1; k <= 9; k++) { if (isRowInValid(curPos.x, k) || isColInValid(curPos.y, k) || isSquareInValid(curPos.x, curPos.y, k)) { continue; } nums[curPos.x][curPos.y] = k; rowMap[curPos.x][k - 1] = true; colMap[curPos.y][k - 1] = true; squareMap[getSquareI(curPos.x, curPos.y)][k - 1] = true; result = traceBack(nums, zeroQueue); squareMap[getSquareI(curPos.x, curPos.y)][k - 1] = false; colMap[curPos.y][k - 1] = false; rowMap[curPos.x][k - 1] = false; if (result) { return true; } } zeroQueue.addFirst(curPos); return result; } private static boolean isRowInValid(int x, int val) { return rowMap[x][val - 1]; } private static boolean isColInValid(int y, int val) { return colMap[y][val - 1]; } private static boolean isSquareInValid(int x, int y, int val) { return squareMap[getSquareI(x, y)][val - 1]; } } class Pos { int x; int y; Pos(int x, int y) { this.x = x; this.y = y; } }