0
点赞
收藏
分享

微信扫一扫

3623、合并两个有序数组

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


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


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

-109 <= nums1[i], nums2[j] <= 109


进阶:你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?


链接:https://leetcode-cn.com/problems/merge-sorted-array

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

package cn.fansunion.leecode.linkedlist;

/**

* 88. 合并两个有序数组 <br/>给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

*

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

*

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

*

* 来源:力扣(LeetCode) 链接:力扣 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

*

* @author wen.lei@brgroup.com

*

* 2022-2-23

*/

public class MergeSortedArray {

/* 示例 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*/

/**

* 思路:目标是把nums2按照顺序插入到nums1,从后向前比较插入;双指针,效率高;<br/>

* 如果nums2有剩余的没插入,需要单独再插入<br/>

* 如果nums1有剩余的没插入,不需要处理,特征是处理nums2,nums2没处理的自然就有序的<br/>

* 官方算法学名:“逆向双指针”。因为算法题经常都是各种“奇思妙想”,“诡计”,突然想到:就是从后向前容易点,逐步替换“0”的过程

* 这道题的“合并数组”,又是有特定要求的;常见的合并数组:nums1+nums2,可以直接new一个nums3,正向遍历nums1和nums2

*

*

* @param nums1

* @param m

* @param nums2

* @param n

*/

public void merge(int[] nums1, int m, int[] nums2, int n) {

int nums1Index = m - 1;

int nums2Index = n - 1;

int curIndex = m + n - 1;

while (nums1Index >= 0 && nums2Index >= 0) {

if (nums1[nums1Index]<= nums2[nums2Index]) {

nums1[curIndex] = nums2[nums2Index];

nums2Index--;

curIndex--;

} else {

nums1[curIndex] = nums1[nums1Index];

nums1Index--;

curIndex--;

}

}

// nums1提前往后挪了,nums2还有剩下的

// 这种题目,边界值的情况经常有,一次性想不全,必须得构造很多测试用例额

while (nums2Index >= 0) {

nums1[nums2Index] = nums2[nums2Index];

nums2Index--;

}

}

/**

* 合并两个有序数组(笨办法),结果还不对<br/>

* [-1,0,0,3,3,3,0,0,0] 6,[1,2,2] 3;输出:[1,2,2,-1,0,0,3,3,3],预期:[-1,0,0,1,2,2,3,3,3]

*

* @param nums1

* nums1 = [1,2,3,0,0,0]

* @param m

* 3 nums2 = [2,5,6]

* @param nums2

* 3

* @param n

* 3 输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。

*/

public void mergeStupidAndError(int[] nums1, int m, int[] nums2, int n) {

// 遍历需要插入的若干数字

for (int nums2Index = 0; nums2Index < n; nums2Index++) {

// 插入1个数字到目标数组里

mergeIntoNums(nums2[nums2Index], nums1);

}

}

// 插入1个数字到目标数组里

private void mergeIntoNums(int newNum, int[] nums) {

// 先找插入位置

int insertIndex = 0;

for (int i = 0; i < nums.length; i++) {

if (nums[i] <= 0 || newNum < nums[i]) {

insertIndex = i;

break;

}

insertIndex++;

}

// 通过2个临时变量的辅助,插入,效果:后面的数字都往后移一位

int cur = newNum;

int next = 0;

for (int index = insertIndex; index < nums.length; index++) {

next = nums[index];

nums[index] = cur;

cur = next;

}

}

/**

* 另外一种形式的合并数组,允许构造新的merge数组并返回,稍微简单点

*

* @param nums1

* @param nums2

* @return

*/

public int[] mergeWithReturn(int[] nums1, int[] nums2) {

int[] nums = new int[nums1.length + nums2.length];

int nums1Index = 0;

int nums2Index = 0;

int curIndex = 0;

// 双指针

while (nums1Index < nums1.length && nums2Index < nums2.length) {

if (nums1[nums1Index] <= nums2[nums2Index]) {

nums[curIndex] = nums1[nums1Index];

nums1Index++;

} else {

nums[curIndex] = nums2[nums2Index];

nums2Index++;

}

curIndex++;

}

// num1有剩余的

while (nums1Index < nums1.length) {

nums[curIndex] = nums1[nums1Index];

nums1Index++;

curIndex++;

}

// nums2有剩余的

while (nums2Index < nums2.length) {

nums[curIndex] = nums2[nums2Index];

nums2Index++;

curIndex++;

}

return nums;

}

}

package test.leecode.linkedlist;

import org.junit.Assert;

import org.junit.Test;

import cn.fansunion.leecode.linkedlist.MergeSortedArray;

/**

* @author wen.lei@brgroup.com

*

* 2022-2-23

*/

public class MergeSortedArrayTest {

@Test

public void test() {

MergeSortedArray test = new MergeSortedArray();

// test2

int[] nums3 = new int[] {2, 3, 5, 0, 0, 0, 0, 0};

int[] nums4 = new int[] {1, 4, 5, 6, 9};

test.merge(nums3, 3, nums4, 5);

Assert.assertArrayEquals(new int[] {1, 2, 3, 4, 5, 5, 6, 9}, nums3);

// test1

int[] nums1 = new int[] {1, 2, 3, 0, 0, 0};

int[] nums2 = new int[] {2, 5, 6};

test.merge(nums1, 3, nums2, 3);

Assert.assertArrayEquals(new int[] {1, 2, 2, 3, 5, 6}, nums1);

// test3

int[] nums5 = new int[] {3, 3, 3, 3, 0, 0, 0, 0};

int[] nums6 = new int[] {1, 1, 2, 2};

test.merge(nums5, 4, nums6, 4);

Assert.assertArrayEquals(new int[] {1, 1, 2, 2, 3, 3, 3, 3}, nums5);

// test4

int[] nums7 = new int[] {1, 1, 2, 3, 0, 0, 0, 0};

int[] nums8 = new int[] {4, 5, 6, 7};

test.merge(nums7, 4, nums8, 4);

Assert.assertArrayEquals(new int[] {1, 1, 2, 3, 4, 5, 6, 7}, nums7);

}

@Test

public void testMergeWithReturn() {

MergeSortedArray test = new MergeSortedArray();

// test2

int[] nums3 = new int[] {2, 3, 5};

int[] nums4 = new int[] {1, 4, 5, 6, 9};

int[] test2 = test.mergeWithReturn(nums3, nums4);

Assert.assertArrayEquals(new int[] {1, 2, 3, 4, 5, 5, 6, 9}, test2);

// test1

int[] nums1 = new int[] {1, 2, 3};

int[] nums2 = new int[] {2, 5, 6};

int[] test1 = test.mergeWithReturn(nums1, nums2);

Assert.assertArrayEquals(new int[] {1, 2, 2, 3, 5, 6}, test1);

// test3

int[] nums5 = new int[] {3, 3, 3, 3};

int[] nums6 = new int[] {1, 1, 2, 2};

int[] test3 = test.mergeWithReturn(nums5, nums6);

Assert.assertArrayEquals(new int[] {1, 1, 2, 2, 3, 3, 3, 3}, test3);

// test4

int[] nums7 = new int[] {1, 1, 2, 3};

int[] nums8 = new int[] {4, 5, 6, 7};

int[] test4 = test.mergeWithReturn(nums7, nums8);

Assert.assertArrayEquals(new int[] {1, 1, 2, 3, 4, 5, 6, 7}, test4);

}

// mergeStupid

public static void main(String[] args) {

// test1

int[] nums1 = new int[] {1, 2, 3, 0, 0, 0};

int[] nums2 = new int[] {2, 5, 6};

MergeSortedArray msa = new MergeSortedArray();

msa.mergeStupidAndError(nums1, 3, nums2, 3);

for (int num : nums1) {

System.out.print(num);

}

System.out.println();

// test2

int[] nums3 = new int[] {2, 3, 5, 0, 0, 0, 0, 0};

int[] nums4 = new int[] {1, 4, 5, 6, 9};

MergeSortedArray msa2 = new MergeSortedArray();

msa2.mergeStupidAndError(nums3, 3, nums4, 5);

for (int num : nums3) {

System.out.print(num);

}

}

}

举报

相关推荐

0 条评论