1.问题描述:
给定两个排序后的数组A和B,其中A的末端有足够的缓冲空间容纳B。编写一个方法,将B 合并入A并排序。
2. 解题思路:
可以通过从后向前合并的方式解决,因为数组A末端有足够的缓冲空间。
3. 图解流程:
使用多张图,演示下面代码的整个流程:
1)初始状态图:
数组A: [1, 3, 5, 0, 0, 0] (m=3)
数组B: [2, 4, 6] (n=3)
指针位置:
i=2 (指向A的5)
j=2 (指向B的6)
k=5 (指向A最后一个0)
2)第一轮比较 (A[2]=5 vs B[2]=6):
6 > 5 → 将6放入A[5]
数组A: [1, 3, 5, 0, 0, 6]
指针移动: j--=1, k--=4
3)第二轮比较 (A[2]=5 vs B[1]=4):
5 > 4 → 将5放入A[4]
数组A: [1, 3, 5, 0, 5, 6]
指针移动: i--=1, k--=3
4)第三轮比较 (A[1]=3 vs B[1]=4):
4 > 3 → 将4放入A[3]
数组A: [1, 3, 5, 4, 5, 6]
指针移动: j--=0, k--=2
5)第四轮比较 (A[1]=3 vs B[0]=2):
3 > 2 → 将3放入A[2]
数组A: [1, 3, 3, 4, 5, 6]
指针移动: i--=0, k--=1
6)第五轮比较 (A[0]=1 vs B[0]=2):
2 > 1 → 将2放入A[1]
数组A: [1, 2, 3, 4, 5, 6]
指针移动: j--=-1, k--=0
7)结束状态:
j=-1 (B已处理完)
最终数组A: [1, 2, 3, 4, 5, 6]
这个流程展示了如何从后向前合并两个已排序数组,避免了元素覆盖问题,且不需要额外空间。每个步骤都通过比较两个数组当前元素,将较大的放入目标位置,直到所有元素处理完毕。
4.代码实现
核心逻辑:
- 指针初始化:
i指向数组A的最后一个有效元素,j指向数组B的末尾,k指向合并后的末尾。 - 从后向前合并:比较
A[i]和B[j],较大者放入A[k]并移动对应指针。 - 处理剩余元素:如果
B中有剩余元素,直接复制到A中。
语言特性:
- PHP 数组自动扩展;使用
array_pad扩展数组A的空间,使其能容纳合并后的所有元素。 - Go:使用切片操作,直接修改传入的切片。
- Java:数组长度固定,需提前预留空间。
- Python:动态扩展列表长度(如
A = [1,3,5] + [0]*3)。
php版本:
function mergeSortedArrays(&$A, $m, $B, $n) {
$i = $m - 1; // A 的有效元素末尾指针
$j = $n - 1; // B 的末尾指针
$k = $m + $n - 1; // 合并后的数组末尾指针
// 从后向前合并
while ($i >= 0 && $j >= 0) {
if ($A[$i] > $B[$j]) {
$A[$k--] = $A[$i--];
} else {
$A[$k--] = $B[$j--];
}
}
// 处理 B 中剩余元素
while ($j >= 0) {
$A[$k--] = $B[$j--];
}
}
// 示例测试
$A = [1, 3, 5]; // 初始有效元素 [1, 3, 5]
$B = [2, 4, 6];
$A = array_pad($A, count($A) + count($B), 0); // 扩展空间
mergeSortedArrays($A, 3, $B, 3);
echo implode(" ", $A); // 输出:1 2 3 4 5 6
python 版本:
def merge_sorted_arrays(A, m, B, n):
i = m - 1 # A的最后一个有效元素索引
j = n - 1 # B的最后一个元素索引
k = m + n - 1 # 合并后的末尾索引
# 从后向前合并,直到A或B处理完毕
while i >= 0 and j >= 0:
if A[i] > B[j]:
A[k] = A[i]
i -= 1
else:
A[k] = B[j]
j -= 1
k -= 1
# 处理B中剩余的元素(若存在)
while j >= 0:
A[k] = B[j]
j -= 1
k -= 1
if __name__ == "__main__":
A = [1, 3, 5] + [0] * 3 # 扩展空间
B = [2, 4, 6]
merge_sorted_arrays(A, 3, B, 3)
print(A) # 输出 [1, 2, 3, 4, 5, 6]
golang版本:
package main
import "fmt"
func mergeSortedArrays(A []int, m int, B []int, n int) {
i, j, k := m-1, n-1, m+n-1
for i >= 0 && j >= 0 {
if A[i] > B[j] {
A[k] = A[i]
i--
} else {
A[k] = B[j]
j--
}
k--
}
// 处理 B 剩余元素
for j >= 0 {
A[k] = B[j]
j--
k--
}
}
func main() {
A := []int{1, 3, 5, 0, 0, 0} // 后三个0为预留空间
B := []int{2, 4, 6}
mergeSortedArrays(A, 3, B, 3)
fmt.Println(A) // 输出 [1 2 3 4 5 6]
}
java 版本:
public class Main {
public static void mergeSortedArrays(int[] A, int m, int[] B, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (A[i] > B[j]) {
A[k--] = A[i--];
} else {
A[k--] = B[j--];
}
}
// 处理 B 剩余元素
while (j >= 0) {
A[k--] = B[j--];
}
}
public static void main(String[] args) {
int[] A = {1, 3, 5, 0, 0, 0}; // 后三个0为预留空间
int[] B = {2, 4, 6};
mergeSortedArrays(A, 3, B, 3);
for (int num : A) {
System.out.print(num + " "); // 输出 1 2 3 4 5 6
}
}
}
5.复杂度分析
- 时间复杂度:O(m + n),遍历两个数组各一次。
- 空间复杂度:O(1),原地操作,无需额外空间。
6.边界测试
- B 全部小于 A:
A = [4,5,6] + [0]*3 B = [1,2,3] merge_sorted_arrays(A, 3, B, 3) print(A) # 输出 [1,2,3,4,5,6] - A 或 B 为空:
A := []int{0, 0, 0} B := []int{1, 2, 3} mergeSortedArrays(A, 0, B, 3) // A为空 fmt.Println(A) // 输出 [1,2,3]
3780

被折叠的 条评论
为什么被折叠?



