数组
回溯
矩阵
题目描述
给定两个正整数 m
和 n
,它们是一个 下标从 0 开始 的二维数组 board
的高度和宽度。还有一对正整数 (r, c)
,它们是骑士在棋盘上的起始位置。
你的任务是找到一个骑士的移动顺序,使得 board
中每个单元格都 恰好 被访问一次(起始单元格已被访问,不应 再次访问)。
返回数组 board
,其中单元格的值显示从 0 开始访问该单元格的顺序(骑士的初始位置为 0)。
注意,如果 0 <= r2 <= m-1 且 0 <= c2 <= n-1
,并且 min(abs(r1-r2), abs(c1-c2)) = 1
且 max(abs(r1-r2), abs(c1-c2)) = 2
,则骑士可以从单元格 (r1, c1)
移动到单元格 (r2, c2)
。
示例 1 :
输入: m = 1, n = 1, r = 0, c = 0
输出: [[0]]
解释 只有一个单元格,骑士最初在其中,因此 1x1 网格中只有一个 0。
示例 2 :
输入: m = 3, n = 4, r = 0, c = 0
输出: [[0,3,6,9],[11,8,1,4],[2,5,10,7]]
解释: 按照以下移动顺序,我们可以访问整个棋盘。
(0,0)->(1,2)->(2,0)->(0,1)->(1,3)->(2,1)->(0,2)->(2,3)->(1,1)->(0,3)->(2,2)->(1,0)
提示:
1 <= m, n <= 5
0 <= r <= m - 1
0 <= c <= n - 1
输入的数据保证在给定条件下至少存在一种访问所有单元格的移动顺序。
解法
方法一:回溯
我们创建一个二维数组 $g$,用于记录骑士的移动顺序,初始时 $g[r][c] = -1$,其余位置均为 $-1$。另外,我们还需要一个变量 $ok$,用于记录是否找到了一种方案。
接下来,我们从 $(r, c)$ 开始进行深度优先搜索,每次搜索位置 $(i, j)$ 时,我们先判断 $g[i][j]$ 是否等于 $m \times n - 1$,若是,说明我们已经找到了一种方案,此时将 $ok$ 置为 true
并且返回。否则我们枚举骑士的八个移动方向对应的位置 $(x, y)$,若满足 $0 \leq x \lt m$, $0 \leq y \lt n$,并且 $g[x][y]=-1$,那么我们将 $g[x][y]$ 更新为 $g[i][j]+1$,然后递归搜索位置 $(x, y)$。如果搜索结束后,变量 $ok$ 为 true
,则直接返回。否则,我们将 $g[x][y]$ 重置为 $-1$,继续搜索其他方向。
最后返回二维数组 $g$ 即可。
时间复杂度 $O(8^{m \times n})$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 为题目给定的整数。
Python3 Java C++ Go TypeScript Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 class Solution :
def tourOfKnight ( self , m : int , n : int , r : int , c : int ) -> List [ List [ int ]]:
def dfs ( i : int , j : int ):
nonlocal ok
if g [ i ][ j ] == m * n - 1 :
ok = True
return
for a , b in pairwise (( - 2 , - 1 , 2 , 1 , - 2 , 1 , 2 , - 1 , - 2 )):
x , y = i + a , j + b
if 0 <= x < m and 0 <= y < n and g [ x ][ y ] == - 1 :
g [ x ][ y ] = g [ i ][ j ] + 1
dfs ( x , y )
if ok :
return
g [ x ][ y ] = - 1
g = [[ - 1 ] * n for _ in range ( m )]
g [ r ][ c ] = 0
ok = False
dfs ( r , c )
return g
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 class Solution {
private int [][] g ;
private int m ;
private int n ;
private boolean ok ;
public int [][] tourOfKnight ( int m , int n , int r , int c ) {
this . m = m ;
this . n = n ;
this . g = new int [ m ][ n ] ;
for ( var row : g ) {
Arrays . fill ( row , - 1 );
}
g [ r ][ c ] = 0 ;
dfs ( r , c );
return g ;
}
private void dfs ( int i , int j ) {
if ( g [ i ][ j ] == m * n - 1 ) {
ok = true ;
return ;
}
int [] dirs = { - 2 , - 1 , 2 , 1 , - 2 , 1 , 2 , - 1 , - 2 };
for ( int k = 0 ; k < 8 ; ++ k ) {
int x = i + dirs [ k ] , y = j + dirs [ k + 1 ] ;
if ( x >= 0 && x < m && y >= 0 && y < n && g [ x ][ y ] == - 1 ) {
g [ x ][ y ] = g [ i ][ j ] + 1 ;
dfs ( x , y );
if ( ok ) {
return ;
}
g [ x ][ y ] = - 1 ;
}
}
}
}
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 class Solution {
public :
vector < vector < int >> tourOfKnight ( int m , int n , int r , int c ) {
vector < vector < int >> g ( m , vector < int > ( n , -1 ));
g [ r ][ c ] = 0 ;
int dirs [ 9 ] = { -2 , -1 , 2 , 1 , -2 , 1 , 2 , -1 , -2 };
bool ok = false ;
function < void ( int , int ) > dfs = [ & ]( int i , int j ) {
if ( g [ i ][ j ] == m * n - 1 ) {
ok = true ;
return ;
}
for ( int k = 0 ; k < 8 ; ++ k ) {
int x = i + dirs [ k ], y = j + dirs [ k + 1 ];
if ( x >= 0 && x < m && y >= 0 && y < n && g [ x ][ y ] == -1 ) {
g [ x ][ y ] = g [ i ][ j ] + 1 ;
dfs ( x , y );
if ( ok ) {
return ;
}
g [ x ][ y ] = -1 ;
}
}
};
dfs ( r , c );
return g ;
}
};
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 func tourOfKnight ( m int , n int , r int , c int ) [][] int {
g := make ([][] int , m )
for i := range g {
g [ i ] = make ([] int , n )
for j := range g [ i ] {
g [ i ][ j ] = - 1
}
}
g [ r ][ c ] = 0
ok := false
var dfs func ( i , j int )
dfs = func ( i , j int ) {
if g [ i ][ j ] == m * n - 1 {
ok = true
return
}
dirs := [] int { - 2 , - 1 , 2 , 1 , - 2 , 1 , 2 , - 1 , - 2 }
for k := 0 ; k < 8 ; k ++ {
x , y := i + dirs [ k ], j + dirs [ k + 1 ]
if x >= 0 && x < m && y >= 0 && y < n && g [ x ][ y ] == - 1 {
g [ x ][ y ] = g [ i ][ j ] + 1
dfs ( x , y )
if ok {
return
}
g [ x ][ y ] = - 1
}
}
}
dfs ( r , c )
return g
}
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 function tourOfKnight ( m : number , n : number , r : number , c : number ) : number [][] {
const g : number [][] = Array . from ({ length : m }, () => Array ( n ). fill ( - 1 ));
const dirs = [ - 2 , - 1 , 2 , 1 , - 2 , 1 , 2 , - 1 , - 2 ];
let ok = false ;
const dfs = ( i : number , j : number ) => {
if ( g [ i ][ j ] === m * n - 1 ) {
ok = true ;
return ;
}
for ( let k = 0 ; k < 8 ; ++ k ) {
const [ x , y ] = [ i + dirs [ k ], j + dirs [ k + 1 ]];
if ( x >= 0 && x < m && y >= 0 && y < n && g [ x ][ y ] === - 1 ) {
g [ x ][ y ] = g [ i ][ j ] + 1 ;
dfs ( x , y );
if ( ok ) {
return ;
}
g [ x ][ y ] = - 1 ;
}
}
};
g [ r ][ c ] = 0 ;
dfs ( r , c );
return g ;
}
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 impl Solution {
pub fn tour_of_knight ( m : i32 , n : i32 , r : i32 , c : i32 ) -> Vec < Vec < i32 >> {
let mut g : Vec < Vec < i32 >> = vec! [ vec! [ - 1 ; n as usize ]; m as usize ];
g [ r as usize ][ c as usize ] = 0 ;
let dirs : [ i32 ; 9 ] = [ - 2 , - 1 , 2 , 1 , - 2 , 1 , 2 , - 1 , - 2 ];
let mut ok = false ;
fn dfs (
i : usize ,
j : usize ,
g : & mut Vec < Vec < i32 >> ,
m : i32 ,
n : i32 ,
dirs : & [ i32 ; 9 ],
ok : & mut bool ,
) {
if g [ i ][ j ] == m * n - 1 {
* ok = true ;
return ;
}
for k in 0 .. 8 {
let x = (( i as i32 ) + dirs [ k ]) as usize ;
let y = (( j as i32 ) + dirs [ k + 1 ]) as usize ;
if x < ( m as usize ) && y < ( n as usize ) && g [ x ][ y ] == - 1 {
g [ x ][ y ] = g [ i ][ j ] + 1 ;
dfs ( x , y , g , m , n , dirs , ok );
if * ok {
return ;
}
g [ x ][ y ] = - 1 ;
}
}
}
dfs ( r as usize , c as usize , & mut g , m , n , & dirs , & mut ok );
g
}
}
GitHub