LeetCode 1768. 交替合并字符串
题目描述


题意分析
合并两个字符串时,从
word1开始,轮流取一个字符追加到结果。两串内部的字符先后顺序都保持不变;当较短的字符串用完后,将较长字符串剩余的全部后缀按原顺序接到末尾。每个输入字符必须使用一次,没有排序、去重或取舍。若两串长度分别为
m、n,最终长度一定为m + n。
解法:按相同下标交替追加,再保留较长后缀
核心思路
[!blue]
在两串都还有字符的阶段,每一轮都会恰好从各自取出一个字符,因此两边已消耗的数量始终相同,可以共用一个下标
i,不需要分别维护两个进度。只要
i < m且i < n,就先追加word1[i],再追加word2[i],然后将i加一。处理完一轮后,两串的前i个字符都已经按要求交替进入结果,而下标i仍指向各自第一个尚未使用的位置。循环结束时,
i等于较短串的长度,至少一边已经用完。因此[i, m)和[i, n)至多有一个非空,把非空的一段整体追加即可,不必继续强行交替,也不会重复使用前面的字符。Java 的
StringBuilder和 Go 的strings.Builder负责顺序收集结果,按已知总长度预留容量可以减少扩容。题目限定小写英文字母,因此 Go 按字节下标读取和追加,与题目中的单个字符含义一致。
解题步骤
- 保存两串长度,为结果预留
m + n的容量,令i = 0。- 两串都未结束时,依次追加当前下标的第一串字符和第二串字符,再推进
i。- 如果第一串仍有剩余,追加
[i, m);如果第二串仍有剩余,追加[i, n)。- 返回构造完成的字符串。
代码实现
class Solution {
public String mergeAlternately(String word1, String word2) {
int m = word1.length();
int n = word2.length();
// 答案长度恒为 m + n,预先把容量设满,底层数组一次分配到位,省掉扩容拷贝
StringBuilder sb = new StringBuilder(m + n);
int i = 0;
// 交替段:两串都还有字符时,按「先 word1 后 word2」成对追加,循环体内无需越界判断
while (i < m && i < n) {
sb.append(word1.charAt(i));
sb.append(word2.charAt(i));
i++;
}
// 剩余段:此时 i == min(m, n),两个条件至多命中一个,整段追加后缀
if (i < m) {
// 注意 append(CharSequence, start, end) 的第三个参数是结束下标,不是长度
sb.append(word1, i, m);
}
if (i < n) {
sb.append(word2, i, n);
}
return sb.toString();
}
}
import (
"strings"
)
func mergeAlternately(word1 string, word2 string) string {
m, n := len(word1), len(word2)
// 答案长度恒为 m + n,先 Grow 到位,避免 Builder 内部反复扩容拷贝
var sb strings.Builder
sb.Grow(m + n)
i := 0
// 交替段:两串都还有字符时,按「先 word1 后 word2」成对追加,循环体内无需越界判断
for i < m && i < n {
// 题目保证只含小写字母,均为单字节,按 byte 取用安全
sb.WriteByte(word1[i])
sb.WriteByte(word2[i])
i++
}
// 剩余段:此时 i == min(m, n),两个条件至多命中一个,整段追加后缀
if i < m {
sb.WriteString(word1[i:])
}
if i < n {
sb.WriteString(word2[i:])
}
return sb.String()
}
复杂度分析
- 时间复杂度:$O(m+n)$,每个输入字符恰好追加一次,最终输出也具有这个长度。
- 空间复杂度:输出缓冲为 $O(m+n)$,除结果存储外只维护常量个长度与下标变量。
关键点总结
[!green]
- 交替阶段两边进度同步,共用一个下标即可。
- 每轮固定先第一串、后第二串,保留各自内部顺序。
- 较短串结束后,只剩另一边的后缀需要一次追加。
易错点总结
[!yellow]
- 先追加
word2,会颠倒题目规定的起始顺序。- 共同阶段使用逻辑或作为循环条件,会在较短串用完后继续访问它的下标。
- 交替循环结束就返回,会漏掉较长串尚未使用的后缀。
- 后缀从
i + 1开始会漏掉第一个未使用字符,应从当前i开始。- Java 的
append(CharSequence, start, end)最后一个参数是结束下标,不是要追加的长度。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 补充题 108. 交替合并两个链表 | 简单 | 同样交替合并并保留较长尾部,链表版本要先保存后继再改指针。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!