058 · Merge Strings Alternately

algorithm
Published

July 15, 2026

My First Thoughts

嗯,刻意要求的一道更容易一点点的题目。

比如:

word1 = "abc"
word2 = "pqr"

这道题需要拼接两个字符串,对吧。

之前应该是遇到过合并两个升序链表的题。这里可能更简单一些,因为不用判断大小,只是按顺序交替拿字符。

应该是维护指针就行了吧?

其实只有一个问题:

如何实现交替,如何退出?

一开始可能会想到维护一个总的 index

如果 index 是偶数,就取 word1

如果 index 是奇数,就取 word2

比如:

index = 0 取 word1[0]
index = 1 取 word2[0]
index = 2 取 word1[1]
index = 3 取 word2[1]

这样就会想到类似:

append(index // 2)
index += 1

不过这里马上会有一点麻烦:当前要取的那个字符串是不是已经用完了。

所以会继续想:

两个指针会好些嘛?

也就是:

result = []
index1 = 0
index2 = 0

index1 表示 word1 取到哪里,用 index2 表示 word2 取到哪里。

然后尝试根据两个指针的大小决定下一步拿哪个字符串:

if index1 <= index2 and index1 < len(word1):
    result.append(word1[index1])
    index1 += 1

elif index1 > index2 and index2 < len(word2):
    result.append(word2[index2])
    index2 += 1

elif index1 > len(word1) and index2 <= len(word2):
    left = word2[index2:]
    return "".join(result) + left

else:
    left = word1[index1:]
    return "".join(result) + left

这个方向是可以的。

真正重要的点已经抓到了:两个字符串各自需要一个位置,最后还要处理剩余部分。

不过这个写法里,边界和分支会有点绕。


Why That Is Not Enough

上面的两个指针思路本身没有错。

问题主要是表达方式有点复杂。

它用:

index1 <= index2
index1 > index2

来判断现在应该取 word1 还是 word2

这样能做,但需要小心维护两个指针之间的关系。再加上两个字符串长度可能不同,后面就会出现比较多的边界分支。

这题其实可以更直接一点。

因为题目要求的是交替合并,而交替合并可以理解成:

每一轮尽量取一对字符:先取 word1 当前字符,再取 word2 当前字符。

也就是说,不需要一次只取一个字符,也不需要用指针大小判断轮到谁。

只要两个字符串都还有字符,就一轮取两个。


Final Idea

还是保留两个指针:

i = 0
j = 0

其中:

  • i 指向 word1 当前要取的位置
  • j 指向 word2 当前要取的位置

先准备一个结果列表:

result = []

当两个字符串都还没有用完时:

while i < len(word1) and j < len(word2):

每一轮就取一对字符:

result.append(word1[i])
result.append(word2[j])
i += 1
j += 1

这样天然就是交替的:

word1[i], word2[j]
word1[i + 1], word2[j + 1]
word1[i + 2], word2[j + 2]

循环结束以后,说明至少有一个字符串已经用完了。

如果 word1 还有剩余,就把剩下的部分接上:

result.append(word1[i:])

如果 word2 还有剩余,也把剩下的部分接上:

result.append(word2[j:])

这里不用再额外判断谁剩下。

因为如果某个字符串没有剩余,切片会得到空字符串:

word1[i:] == ""

把空字符串 append 进去也不影响最后结果。


Why It Works

题目要求从 word1 开始交替取字符。

word1word2 都还有字符时,每一轮执行:

result.append(word1[i])
result.append(word2[j])

这正好对应:

先取 word1 的当前字符
再取 word2 的当前字符

然后两个指针同时往后移动一格:

i += 1
j += 1

所以下一轮会继续取下一对字符。

当循环结束时,至少有一个字符串已经没有字符可以取了。

这时候交替已经无法继续,只需要按照题意,把另一个字符串剩下的字符直接接到结果后面。

用切片:

word1[i:]
word2[j:]

正好表示两个字符串还没有取过的部分。

如果其中一个已经用完,它的剩余部分就是空字符串,不会改变答案。

例如:

word1 = "ab"
word2 = "pqrs"

先取两轮:

a p b q

这时 word1 用完了,word2[j:]"rs"

所以最后得到:

"apbqrs"

Code

def mergeAlternately(word1, word2):
    result = []
    i = 0
    j = 0

    while i < len(word1) and j < len(word2):
        result.append(word1[i])
        result.append(word2[j])
        i += 1
        j += 1

    result.append(word1[i:])
    result.append(word2[j:])

    return "".join(result)

Complexity

Time \(O(n + m)\) - nword1 的长度,mword2 的长度;每个字符都会被加入结果一次
Space \(O(n + m)\) - result 需要保存合并后的字符串内容

Takeaway

如果题目要求“交替处理两个序列”,不一定要用一个总下标和奇偶判断。也可以用两个指针,每一轮同时处理一对元素;等其中一个序列用完后,再把另一个序列的剩余部分接上。


Quiz