求star

开源不易,喜欢请点个star吧

Ocean Han
1006 字
5 分钟
Leetcode->合并两个有序数组
2022-03-23

题目:tada:#

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/

示例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
    • -109 <= nums1[i], nums2[j] <= 109

解题#

1. 先替换,后排序#

思路#

TIP

先用nums2中的元素替换nums1中的 0,然后进行排序即可

代码#

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    //用nums2替换nums1中的0
    nums1.splice(m,n,...nums2)
    //升序排序
    nums1.sort((a,b)=> a-b)
};
WARNING

思路是好的,不过直接这样写,面试官大概会让你滚出去了…

但令人激动的是,这是目前为数不多,自己写的和官方题解几乎一样

2. 双指针#

思路#

TIP

这题和之前做过的一道 合并有序链表 很像,所以很快就想到了双指针的解法

将两个数组看作队列,每次都从两个数组头部,取出比较小的数放进结果中

代码#

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    //定义两个指针
    let p1 = 0, p2 = 0;
    //创建长度为 m+n的数组res,并用0初始化
    const res = new Array(m + n).fill(0);
    var cur;
    //如果两个指针都到底了,说明已经遍历完成
    while (p1 < m || p2 < n) {
        //若P1==m(p2==n),则说明nums1(nums2)已经遍历完成,则只需要将nums2(nums1)加到后面即可
        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++];
        }
        res[p1 + p2 - 1] = cur;
    }
    //将结果复制到nums1中(题目要求直接在nums1上修改)
    for (let i = 0; i != m + n; ++i) {
        nums1[i] = res[i];
    }
};

3. 逆向双指针#

思路#

TIP

在上一个方法(正向双指针)中,之所以用一个临时变量cur,是为了避免nums1中的元素在取出来之前就被覆盖了

但根据题意,nums1的后半部分是空(0),直接覆盖不会影响结果,所以可以让指针从后往前遍历,每次取两者中的最大值放入nums1后半部分

代码#

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    //用来遍历的两个指针(从后往前)
    let p1 = m - 1, p2 = n - 1;
    //指向当前要插入的位置
    let tail = m + n - 1;
    var cur;
    while (p1 >= 0 || p2 >= 0) {
        if (p1 === -1) {
            cur = nums2[p2--];
        } else if (p2 === -1) {
            cur = nums1[p1--];
        } else if (nums1[p1] > nums2[p2]) {
            cur = nums1[p1--];
        } else {
            cur = nums2[p2--];
        }
        nums1[tail--] = cur;
    }
};

Leetcode->合并两个有序数组
https://blog.oceanh.top/posts/algorithm/合并两个有序数组/
作者
Ocean Han
发布于
2022-03-23
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49