面试经典150题-01:合并两个有序数组

76 阅读2分钟

面试经典150题-01:合并两个有序数组

  • 题目链接 leetcode.cn/problems/me…

    懒得复制题目描述了,直接用截图代替了,hhh 在这里插入图片描述 首先这个题目,我想到的是使用堆来解决。因为堆可以每次将最大值或者最小值弹出,我们就可以保证顺序了。

  1. 先将数组1与数组2符合的数据添加到堆中
  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),看了题解后发现题目已经在引导我们使用双指针了。

思路:

  1. 建立indexA、indexB 分别用来遍历数组1与数组2,indexA、indexB默认值都为0
  2. 构建比较的边界,如果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) 在这里插入图片描述