Merge Sorted Arrays
Merge Sorted Array
Lintcode https://www.lintcode.com/problem/64/
Leetcode https://leetcode.com/problems/merge-sorted-array/
题目描述
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意: 最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
public void mergeSortedArray(int[] A, int m, int[] B, int n)
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
- nums1.length == m + n
- nums2.length == n
- 0 <= m, n <= 200
- 1 <= m + n <= 200
- -10^9 <= nums1[i], nums2[j] <= 10^9
进阶:你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?
解题报告
“数组的整体挪动”操作的时间复杂度是 O(n)
小的trick:从最大的开始合并,那就可以从空的地方开始。可以 O(m+n) 完成
最直观的方法是将数组 A 放进数组 B 的尾部,然后直接对整个数组进行排序。
1
2
3
4
5
6
7
8
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for (int i = 0; i != n; ++i) {
nums1[m + i] = nums2[i];
}
Arrays.sort(nums1);
} // end merge
} // end Solution
第二种方法,从前往后,双指针一个指向 nums1,另一个指向 nums2,每次取较小的数出来给 ans,然后最后,把 ans 复制给 nums1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = 0, p2 = 0, cur = 0;
int[] ans = new int[m + n];
while (p1 != m || p2 != n) {
if (p1 == m) {
cur = nums2[p2++];
} else if (p2 == n) {
cur = nums1[p1++];
} else if (nums1[p1] <= nums2[p2]) {
cur = nums1[p1++];
} else {
cur = nums2[p2++];
}
ans[p1 + p2 - 1] = cur;
} // end while loop
for (int i = 0; i < ans.length; i++) {
nums1[i] = ans[i];
} // end for loop
} // end merge
} // end Solution
第3种方法,不用开辟新的数组,直接用给的,从后往前比较大小,取较大的放到数组的最后面来填充数组。
不会覆盖的原因,一句话就能说明白:
把 nums1 的数字移到另一个空位,又产生了一个新的空位,空位个数不变,所以总是有空位可以让 nums2 的数字填入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m - 1;
int p2 = n - 1;
int p = m + n -1;
while (p2 >= 0) { // nums2 还有要合并的元素
// 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中
if (p1 >= 0 && nums1[p1] > nums2[p2]) {
nums1[p] = nums1[p1];
p1 -= 1;
} else {
nums1[p] = nums2[p2];
p2 -= 1;
}
p -= 1; // 更新下一个要填充的位置
} // end while loop
} // end merge
} // end Solution
Merge Two Sorted Arrays
Lintcode https://www.lintcode.com/problem/6/
Solution https://www.jiuzhang.com/solutions/merge-sorted-array-ii/
五星级重要!!!!!
题目描述
将按升序排序的整数数组A和B合并,新数组也需有序。 public int[] mergeSortedArray(int[] a, int[] b)
样例 1:
输入: A = [1] B = [1]
输出: [1,1]
解释:返回合并后的数组。
样例 2:
输入: A = [1,2,3,4] B = [2,4,5,6]
输出: [1,2,2,3,4,4,5,6]
挑战 如果一个数组很大,另一个数组很小,你将如何优化算法?
解题报告
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
/**
* @param A and B: sorted integer array A and B.
* @return: A new sorted integer array
*/
public int[] mergeSortedArray(int[] A, int[] B) {
// Write your code here
int[] ans = new int[A.length + B.length];
int a = 0, b = 0, temp = 0;
while(a != A.length && b != B.length) {
if(A[a] > B[b]){
ans[temp] = B[b++];
}
else {
ans[temp] = A[a++];
}
temp ++;
}
if(a != A.length){
while(a != A.length){
ans[temp++] = A[a++];
}
} else {
while(b != B.length){
ans[temp++] = B[b++];
}
}
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Solution {
/**
* @param a: sorted integer array A
* @param b: sorted integer array B
* @return: A new sorted integer array
*/
public int[] mergeSortedArray(int[] a, int[] b) {
// write your code here
int[] ans = new int[a.length + b.length];
int p1 = 0;
int p2 = 0;
int p = 0;
while (p1 != a.length && p2 != b.length) {
if (a[p1] > b[p2]) {
ans[p] = b[p2++];
} else {
ans[p] = a[p1++];
}
p++;
} // end while loop
if (p1 != a.length) {
while (p1 != a.length) {
ans[p++] = a[p1++];
} // end
} else {
while (p2 != b.length) {
ans[p++] = b[p2++];
} // end while loop
}
return ans;
} // end mergeSortedArray
} // end Solution
Merge K Sorted Arrays
Lintcode https://www.lintcode.com/problem/486/
题目描述
将 k 个有序数组合并为一个大的有序数组。
样例 1:
1
2
3
4
5
6
7
Input:
[
[1, 3, 5, 7],
[2, 4, 6],
[0, 8, 9, 10, 11]
]
Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
样例 2:
1
2
3
4
5
6
Input:
[
[1,2,3],
[1,2]
]
Output: [1,1,2,2,3]
解题报告
可以用堆做到 O(N log k) 的时间复杂度.
初始将所有数组的首个元素入堆, 并记录入堆的元素是属于哪个数组的.
每次取出堆顶元素, 并放入该元素所在数组的下一个元素.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Element {
public int row, col, val;
Element(int row, int col, int val) {
this.row = row;
this.col = col;
this.val = val;
}
}
public class Solution {
private Comparator<Element> ElementComparator = new Comparator<Element>() {
public int compare(Element left, Element right) {
return left.val - right.val;
}
};
/**
* @param arrays k sorted integer arrays
* @return a sorted array
*/
public int[] mergekSortedArrays(int[][] arrays) {
if (arrays == null) {
return new int[0];
}
int total_size = 0;
Queue<Element> Q = new PriorityQueue<Element>(
arrays.length, ElementComparator);
for (int i = 0; i < arrays.length; i++) {
if (arrays[i].length > 0) {
Element elem = new Element(i, 0, arrays[i][0]);
Q.add(elem);
total_size += arrays[i].length;
}
}
int[] result = new int[total_size];
int index = 0;
while (!Q.isEmpty()) {
Element elem = Q.poll();
result[index++] = elem.val;
if (elem.col + 1 < arrays[elem.row].length) {
elem.col += 1;
elem.val = arrays[elem.row][elem.col];
Q.add(elem);
}
}
return result;
}
}
Related
Merge K Sorted Lists
Merge K Sorted Arrays
Merge K Sorted Interval Lists