Problem: 1971. 寻找图中是否存在路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { int [] pa; public boolean validPath (int n, int [][] edges, int source, int destination) { pa = new int [n]; Arrays.setAll(pa, i -> i); for (int [] e : edges) { pa[find(e[0 ])] = find(e[1 ]); } return find(source) == find(destination); } private int find (int a) { return (pa[a] == a) ? a : (pa[a] = find(pa[a])); } }
37解数独
Problem: 37. 解数独
思路 :
利用row[i][val]表示第i行有没有val出现。
利用col[j][val]表示第j列有没有val出现。
利用block[i / 3][j / 3][val]表示第(i/3,j/3)个九宫格有没有val出现。
利用empCells存储尚未被填充的点。
首先取出empCells中的第一个点,digital从0~9填充,如果digital不在行,列,其所在九宫格中存在,则遍历下一个未被填充的点。直到填充结束。
注意点 :
1、在digital遍历的时候,需要加上 !valid 条件。也就是(int digital = 0; digital < 9 && !valid; digital ++)。为什么?
因为如果不加这个条件,假设找到数独的解时,整个dfs还未完成。就要进行回溯,回溯的时候会将先前已经遍历过的digital设置为false。这样的话,当回溯到某个点时,该点的digital从k~9遍历(k是未被遍历过的第一个数字),而恰好在之前回溯过程中,k被设置为false,k在该点的行,列,所在九宫格中均为出现,那么k就会覆盖之前的解中的board[i][j],使得解出错。
举个例子,如下图。dfs在最后的红色1处找到解。此时进行回溯。它一定会回溯到蓝色的1处。这时,由于1下方的7和有方的7都已经被释放了。那么这个时候蓝色的1处就可以填充7,然后接着遍历。就会覆盖正确解的数值。因为board[i][j]在回溯的时候,我们并没有进行对board[i][j]恢复现场。我们仅仅采用了覆盖之前值的方式来回溯。
2、不能使用队列来存储未被确定的点。因为频繁的出队、入队,相当耗时。
是的,自己看图吧。说多了都是泪。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution { private boolean [][] row = new boolean [9 ][9 ]; private boolean [][] col = new boolean [9 ][9 ]; private boolean [][][] block = new boolean [3 ][3 ][9 ]; List<int []> empCells = new ArrayList <int []>(); boolean valid; public void solveSudoku (char [][] board) { for (int i = 0 ; i < 9 ; i ++) { for (int j = 0 ; j < 9 ; j ++) { if (board[i][j] == '.' ) { empCells.add(new int []{i, j}); } else { int digital = board[i][j] - '1' ; row[i][digital] = col[j][digital] = block[i / 3 ][j / 3 ][digital] = true ; } } } dfs(board, 0 ); } private void dfs (char [][] board,int index) { if (index == empCells.size()) { valid = true ; return ; } int [] e = empCells.get(index); int x = e[0 ], y = e[1 ]; for (int i = 0 ; i < 9 && !valid; i ++) { if (!row[x][i] && !col[y][i] && !block[x / 3 ][y / 3 ][i]) { row[x][i] = col[y][i] = block[x / 3 ][y / 3 ][i] = true ; board[x][y] = (char ) ('1' + i); dfs(board, index + 1 ); row[x][i] = col[y][i] = block[x / 3 ][y / 3 ][i] = false ; } } } }