【Day 4】公开打卡第4天 | LeetCode 6. Z 字形变换 + 方向标志法模拟
正文结构:
-
今日打卡宣言 Day 4,坚持第4天了!把这道经典 Z 字形题手写了一遍。连续4天没断,感觉刷题的手感在慢慢回来。继续冲,欢迎监督!
-
LeetCode 部分
已解答
中等
相关标签
相关企业
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"
示例 2:
输入: s = "PAYPALISHIRING", numRows = 4
输出: "PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
示例 3:
输入: s = "A", numRows = 1
输出: "A"
提示:
-
1 <= s.length <= 1000 -
s由英文字母(小写和大写)、','和'.'组成 -
1 <= numRows <= 1000- 题目链接:leetcode.cn/problems/zi… (或英文:leetcode.com/problems/zi…)
- 难度:中等
- 时间复杂度:O(n),n = s.length()
- 核心思路(简短): 模拟 Z 字形书写过程:从上往下写到第 numRows 行后,转向上写到第 1 行,再向下……用一个 flag(或 direction)来控制当前行是 +1 还是 -1。每个字符追加到对应行的字符串,最后拼接所有行。
- 代码(你提供的 C++ 版本,稍加注释,更易懂):
C++
class Solution {
public:
string convert(string s, int numRows) {
if (numRows < 2) return s; // 1行或0行直接返回原串
vector<string> rows(numRows); // 每行一个字符串
int i = 0; // 当前行索引
int flag = -1; // 方向:-1 向上,+1 向下
for (char c : s) {
rows[i] += c; // 当前字符追加到当前行
// 到达顶部或底部时,翻转方向
if (i == 0 || i == numRows - 1) {
flag = -flag;
}
i += flag; // 移动到下一行
}
string res;
for (auto& str : rows) {
res += str; // 按行拼接
}
return res;
}
};
- Go 版本(如果你想双语放一个,方便读者):
Go
func convert(s string, numRows int) string {
if numRows < 2 || len(s) <= numRows {
return s
}
rows := make([]string, numRows)
i, flag := 0, -1
for _, c := range s {
rows[i] += string(c)
if i == 0 || i == numRows-1 {
flag = -flag
}
i += flag
}
var res strings.Builder
for _, row := range rows {
res.WriteString(row)
}
return res.String()
}
-
易错点/优化点:
- numRows == 1 时直接返回 s(边界)。
- flag 初始 -1 是巧妙的(从第0行开始向下时先不翻转)。
- i += flag 后不会越界,因为在边界时刚好翻转。
- 面试追问:不用额外空间 O(1) 怎么做?(数学公式直接计算每个字符位置,但代码更复杂,今天这个模拟法最直观)。 示例:s = "PAYPALISHIRING", numRows = 3 → "PAHNAPLSIIGYIR"
-
知识点部分(今天配 C++ vector 使用 & strings.Builder 在 Go 中的优势) C++ vector 拼接 & Go strings.Builder 高效拼接
-
C++:vector 每行独立追加,最后 for 循环 +=(现代 C++ string 优化较好,但仍可能有多次分配)。
-
Go:直接 += 会产生很多临时 string(因为 string 不可变),推荐用 strings.Builder:
- WriteString 无需中间拷贝,性能更好。
-
面试常问:大量字符串拼接怎么优化?(C++ reserve 容量;Go 用 Builder 或 bytes.Buffer)。
-
这题 n ≤ 1000,影响不大,但养成好习惯。
-
-
今日感悟 这道题以前觉得“找规律难”,今天用方向标志法写完才发现其实很简单——就是模拟过程 + 边界翻转。公开打卡让我必须把代码跑通、边界考虑全,不然发出去没底气。Day 4 了,坚持的感觉真不错,离目标又近了一点!
-
结束语 明天见! 欢迎评论区:① 你的 Z 字形写法(有数学公式解吗?) ② 代码哪里还能改进 ③ 你刷这题花了多久 #程序员打卡 #LeetCode #Z字形变换 #C++ #Go语言