LeetCode 88. 合并两个有序数组
题目描述
思路分析
解法一:从后往前双指针(推荐)
核心思路:
nums1有足够空间,直接从数组尾部开始填充。- 指针
i指向nums1有效末尾,j指向nums2末尾,k指向最终末尾。- 每次将较大的数放到
nums1[k],并移动对应指针。
复杂度分析:
- 时间复杂度:O(m + n),其中 m、n 分别表示两个数组长度。
- 空间复杂度:O(1),仅使用常数额外空间。
// 从后向前合并
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1;
int j = n - 1;
int k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k] = nums1[i];
i--;
} else {
nums1[k] = nums2[j];
j--;
}
k--;
}
while (j >= 0) {
nums1[k] = nums2[j];
j--;
k--;
}
}
}
// 从后向前合并
func merge(nums1 []int, m int, nums2 []int, n int) {
i := m - 1
j := n - 1
k := m + n - 1
for i >= 0 && j >= 0 {
if nums1[i] > nums2[j] {
nums1[k] = nums1[i]
i--
} else {
nums1[k] = nums2[j]
j--
}
k--
}
for j >= 0 {
nums1[k] = nums2[j]
j--
k--
}
}
解法二:额外数组合并
核心思路:
- 使用额外数组按顺序归并两个有序数组。
- 再将结果拷贝回
nums1。
复杂度分析:
- 时间复杂度:O(m + n),其中 m、n 分别表示两个数组长度。
- 空间复杂度:O(m + n),用于临时数组。
// 额外数组合并
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] temp = new int[m + n];
int i = 0, j = 0, k = 0;
while (i < m && j < n) {
if (nums1[i] <= nums2[j]) {
temp[k++] = nums1[i++];
} else {
temp[k++] = nums2[j++];
}
}
while (i < m) {
temp[k++] = nums1[i++];
}
while (j < n) {
temp[k++] = nums2[j++];
}
for (int t = 0; t < m + n; t++) {
nums1[t] = temp[t];
}
}
}
// 额外数组合并
func merge(nums1 []int, m int, nums2 []int, n int) {
temp := make([]int, 0, m+n)
i, j := 0, 0
for i < m && j < n {
if nums1[i] <= nums2[j] {
temp = append(temp, nums1[i])
i++
} else {
temp = append(temp, nums2[j])
j++
}
}
for i < m {
temp = append(temp, nums1[i])
i++
}
for j < n {
temp = append(temp, nums2[j])
j++
}
copy(nums1, temp)
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 21. 合并两个有序链表 | 简单 | 双指针 |
| 977. 有序数组的平方 | 简单 | 双指针 |
| 986. 区间列表的交集 | 中等 | 双指针 |
| 2516. 每种字符至少取 K 个 | 中等 | 滑动窗口 |
| 23. 合并 K 个升序链表 | 困难 | 分治、堆 |
| 283. 移动零 | 简单 | 双指针 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!

