🤖 AI总结
主题
力扣3963题:构造恰好一条路径的网格解法
摘要
力扣3963题要求构造恰好一条路径的m×n网格,解法为第一行全通、后续行仅最后一列可通行,并给出多语言代码实现。
关键信息
- 1 给定m行n列网格,用’.’和’#’构造恰好一条从左上到右下的路径
- 2 解法:第一行全为’.’,后续行前n-1个为’#’,最后一个为’.’
- 3 提供了Go、Python、C++三种语言的完整代码实现
2026-09-21:构造恰好一条路径的网格。用go语言,给定两个整数 m 和 n,它们分别代表一个矩形网格的行数和列数。
请生成任意一个大小为 m 行、n 列的网格,网格中的每个格子只能填写两种字符:
“.” 表示可以通行的空格;
“ 表示不能通行的障碍格。
在这个网格中,从最左上角的格子出发,到达最右下角的格子时,每一步只能往右走一格,或者往下走一格,并且只能经过“.”格。要求从起点到终点能够走通的路线数量正好为 1 条。
请返回任意一个满足这个条件的网格布局。
1 <= m, n <= 25。
输入: m = 2, n = 3。
输出: [“..#”,”#..”]。
解释:
![]()
在这里插入图片描述
唯一的有效路径是:(0,0) → (0,1) → (1,1) → (1,2)
题目来自力扣3963。
大体步骤如下:
第一步:准备结果容器
程序先创建一个长度为 m 的字符串数组,用来保存最终的 m 行网格。每一行最终都是一个由字符 “.” 和 “ 组成的字符串。
第二步:构造第一行
第一行被直接构造成 n 个 “.”。也就是说,第一行的所有格子都是可以通行的空单元格,没有任何障碍物。
第三步:构造后面所有行使用的模板
程序预先构造一个“后续行模板”。这个模板的内容是:前 n-1 个字符全部是 “,最后一个字符是 “.”。
如果 n 等于 1,那么 n-1 就是 0,所以这个模板实际上只有一个 “.”,也就是整行只有一个可通行格子。
这样构造模板的好处是,只需要创建一次字符串,后面每一行都可以重复使用它,避免在循环里反复拼接字符串。
第四步:填充第 2 行到第 m 行
从第二行开始,一直到第 m 行,每一行都直接使用刚才构造好的模板。
因此,除了第一行之外,其余所有行的前 n-1 个格子都是障碍物 “,只有最后一列的格子是空单元格 “.”。
第五步:返回网格
最后,程序返回这个字符串数组,它表示一个满足条件的 m 行 n 列网格。
为什么这个网格恰好只有一条有效路径?
从起点 (0, 0) 开始,它位于第一行。第一行全是 “.”,所以可以向右走。
但是,如果从第一行往下走,进入第二行时,第二行的前 n-1 列都是 “,只有最后一列是 “.”。
因此,如果从第一行的非最后一列往下走,就会进入障碍物,这是不允许的。
所以,从起点出发,只能一直沿着第一行向右走,直到到达第一行的最后一列,也就是 (0, n-1)。
到达 (0, n-1) 后,右边已经没有格子了,只能向下走,进入 (1, n-1)。
而 (1, n-1) 是第二行的最后一列,它是 “.”。
接下来,因为每一行的最后一列都是 “.”,而其他列都是 “,所以从 (1, n-1) 开始也只能继续向下走,最终到达右下角 (m-1, n-1)。
因此,整条路径被唯一确定:先沿第一行一直向右走到最右端,再沿最后一列一直向下走到最底端。
不存在第二条有效路径。
对于题目中给出的例子 m = 2,n = 3,这段代码会生成:
第一行:“…”
第二行:“##.”
也就是网格:
它的唯一有效路径是:(0,0) → (0,1) → (0,2) → (1,2)。
而题目描述里给出的输出示例 [“.., “#..”] 是另一种同样合法的构造,只是障碍物摆放方式不同,但都满足“恰好一条有效路径”的要求。
边界情况说明:
当 m = 1 时,只有第一行,第一行全是 “.”,从左上角到右下角只能一直向右走,路径唯一。
当 n = 1 时,只有一列,第一行是 “.”,后续每一行模板也只有一个 “.”,从左上角到右下角只能一直向下走,路径也唯一。
时间复杂度:
构造第一行需要 O(n) 时间。
构造后续行模板也需要 O(n) 时间。
创建一个长度为 m 的结果数组需要 O(m) 时间。
把模板赋给后面 m-1 行,每次只是字符串引用赋值,可以看作 O(1),总共 O(m)。
所以总时间复杂度是 O(m + n)。
额外空间复杂度:
结果数组本身占 O(m) 个字符串头。
第一行字符串占 O(n) 个字符。
后续行模板字符串占 O(n) 个字符。
由于后面所有行都共享同一个模板字符串,并没有为每一行单独复制一份长度为 n 的字符内容。
因此,算法额外使用的空间是 O(m + n)。
如果把最终输出中每一行的完整字符都单独展开计算,那么字符总数是 m × n,空间会是 O(m × n),但这段代码通过共享字符串减少了实际存储。
Go完整代码如下:
package main
import (
"fmt"
"strings"
)
func createGrid(m, n int) []string {
ans := make([]string, m)
ans[0] = strings.Repeat(".", n)
row := strings.Repeat("#", n-1) + "." // 避免在循环中反复创建字符串
for i := 1; i < m; i++ {
ans[i] = row
}
return ans
}func main() {
m := 2
n := 3
result := createGrid(m, n)
fmt.Println(result)
}
![]()
Python完整代码如下:
# -*-coding:utf-8-*-
def create_grid(m, n):
# 第一行全是空单元格
ans = ['.' * n]
# 后续每一行:前 n-1 个是障碍物,最后一个是空单元格
row = '#' * (n - 1) + '.'
for _ in range(1, m):
ans.append(row)
return ans
def main():
m = 2
n = 3
result = create_grid(m, n)
print(result)if __name__ == '__main__':
main()
![]()
C++完整代码如下:
std::vector
string
> createGrid(
int
m,
int
n) {
std::vector
string
> ans(m);
ans[
0
] = std::
string
(n,
'.'
);
// 第一行全是空单元格
std::
string
row = std::
string
(n -
1
,
'#'
) +
"."
;
// 后续行:前 n-1 个障碍物,最后一个是空单元格
for
(
int
i =
1
; i < m; ++i) {
ans[i] = row;
}
return
ans;
}
int
main() {
int
m =
2
;
int
n =
3
;
std::vector
string
> result = createGrid(m, n);
std::cout <<
"["
;
for
(size_t i =
0
; i < result.size(); ++i) {
if
(i >
0
) std::cout <<
" "
;
std::cout << result[i];
}
std::cout <<
"]"
<< std::endl;
return
0
;
}
![]()
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。