面试题 10.01. 合并排序的数组

文章介绍了如何将两个已排序的数组A和B合并到一起,A有足够空间容纳B。提供了两种解法:一是使用双指针法,从数组末尾开始比较并合并;二是运用归并排序,先合并再排序。两种方法的时间复杂度分别为O(m+n)和O((m+n)log(m+n))。
摘要由CSDN通过智能技术生成

题目描述

有两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

示例

输入:

A = [1,2,3,0,0,0]

B = [2,5,6]

输出:

[1,2,2,3,5,6]

解法一:双指针法

思路:

使用双指针法,从 A 数组和 B 数组的末尾开始比较两个数组的元素,将较大的元素放到 A 数组的末尾。

具体过程如下:

  1. 初始化双指针 i 和 j 分别指向 A 数组和 B 数组的末尾。
  2. 初始化指针 k 指向 A 数组的最后一个元素。
  3. 从后往前比较 A[i] 和 B[j],将较大的元素放到 A[k] 的位置上,同时将指针 i、j 和 k 向前移动一位。
  4. 如果 A 数组遍历结束了,将 B 数组中剩余的元素复制到 A 数组中。

时间复杂度为 O ( m + n ) O(m+n) O(m+n),其中 m 和 n 分别是 A 数组和 B 数组的长度。

代码:(双指针法,时间复杂度 O ( m + n ) O(m+n) O(m+n)

class Solution {
    public void merge(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];
                i--;
            } else {
                A[k] = B[j];
                j--;
            }
            k--;
        }
        while (j >= 0) {
            A[k] = B[j];
            j--;
            k--;
        }
    }
}

解法二:归并排序

思路:

将 A 数组的前 m 个元素和 B 数组合并成一个有序数组,然后将其复制到 A 数组中。

具体过程如下:

  1. 将 A 数组的前 m 个元素和 B 数组复制到一个新的数组中,记为 C 数组。
  2. 对 C 数组进行归并排序,排序完成后将 C 数组的元素复制回 A 数组。

时间复杂度为 O ( ( m + n ) log ⁡ ( m + n ) ) O((m+n)\log(m+n)) O((m+n)log(m+n)),其中 m 和 n 分别是 A 数组和 B 数组的长度。

代码:(归并排序,时间复杂度 O ( ( m + n ) log ⁡ ( m + n ) ) O((m+n)\log(m+n)) O((m+n)log(m+n))

class Solution {
    public void merge(int[] A, int m, int[] B, int n) {
        int[] C = new int[m + n];
        System.arraycopy(A, 0, C, 0, m);
        System.arraycopy(B, 0, C, m, n);
        mergeSort(C, 0, m + n - 1);
        System.arraycopy(C, 0, A, 0, m + n);
    }

    private void mergeSort(int[] nums, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = (left + right) >>> 1;
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        merge(nums, left, mid, right);
    }

    private void merge(int[] nums, int left, int mid, int right) {
        int[] tmp = new int[right - left + 1];
        int i = left, j = mid + 1, k = 0;
        while (i <= mid && j <= right) {
            if (nums[i] <= nums[j]) {
                tmp[k++] = nums[i++];
            } else {
                tmp[k++] = nums[j++];
            }
        }
        while (i <= mid) {
            tmp[k++] = nums[i++];
        }
        while (j <= right) {
            tmp[k++] = nums[j++];
        }
        System.arraycopy(tmp, 0, nums, left, right - left + 1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值