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助力您的未来发展。