面试经典150题-01:合并两个有序数组
-
懒得复制题目描述了,直接用截图代替了,hhh
首先这个题目,我想到的是使用堆来解决。因为堆可以每次将最大值或者最小值弹出,我们就可以保证顺序了。
- 先将数组1与数组2符合的数据添加到堆中
- 将数组1的直接使用堆进行覆盖
要仔细读题,我犯了一个错误就是题目已经说明了数组1是使用前m个元素,我没有get到,导致走了一点弯路,hhh
public void merge(int[] nums1, int m, int[] nums2, int n) {
PriorityQueue<Integer> queue = new PriorityQueue<>(Comparator.comparingInt(o -> o));
for (int i = 0; i < m; i++) {
queue.add(nums1[i]);
}
for (int num : nums2) {
queue.add(num);
}
int size = queue.size();
for (int i = 0; i < size; i++) {
nums1[i] = queue.poll();
}
}
耗时3ms
虽然是成功AC,但是堆排序的时间复杂度是O(NlogN),看了题解后发现题目已经在引导我们使用双指针了。
思路:
- 建立indexA、indexB 分别用来遍历数组1与数组2,indexA、indexB默认值都为0
- 构建比较的边界,如果indexA的值等于m时,就不需要再访问数组1了,同理indexB的值等于n的时候就不需要访问数组2了。开始可以使用三元运算符来比较先获取数组1的值还是先获取数组2的值,有一个条件满足时跳出循环,将另一个数组遍历完即可 代码如下
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] res = new int[m + n];
int indexA = 0;
int indexB = 0;
int index = 0;
while (indexA < m && indexB < n) {
res[index++] = nums1[indexA] <= nums2[indexB] ? nums1[indexA++] : nums2[indexB++];
}
while (index < (m + n)) {
res[index++] = indexA < m ? nums1[indexA++] : nums2[indexB++];
}
index = 0;
for (int re : res) {
nums1[index++] = re;
}
}
只需要一次遍历即可完成数组的合并时间复杂度为O(N)