88.合并两个有序数组

ops/2024/12/15 18:33:35/

题目描述:

给你两个按 非递减顺序 排列的整数数组 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 中。

暴力思路&解法:

1、注意题目:nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0,nums2 的长度为 n

2、题目中明确nums1中后n个元素为0,且nums2的长度为n;那么直接用nums2中的有效元素替换掉nums1中value=0的下标位,再对nums1进行排序,over,直接开整

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int i = 0;int j = 0;// 用nums2中的元素值直接替换nums1中的0while (i < nums1Size && j < nums2Size) {if (nums1[i] == 0) {nums1[i] = nums2[j];j++;}i++;}// 不知道什么排序,冒泡? 反正是排上了for (int i = 0; i < nums1Size - 1; i++) {for (int j = i + 1; j < nums1Size; j++) {if (nums1[i] > nums1[j]) {int temp = nums1[j];nums1[j] = nums1[i];nums1[i] = temp;   }}}
}

3、运行提交没有问题,测试用例ok,抄作业是足够了;但进阶要求时间复杂度为O(m+n),解题思路也有点挫,学习一下其他优解~


优解思路&解法一(C)-- 直接合并后排序:

将数组nums2放进数组nums1的尾部,然后直接对整个数组进行排序.....

int cmp(int* a, int* b) {return *a - *b;
}void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {for (int i = 0; i < n; i++) {nums1[m + i] = nums2[i];}qsort(nums1, nums1Size, sizeof(int), cmp);
}

时间复杂度:排序序列长度为 m+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n));

空间复杂度:排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n));

知识点:快速排序的空间复杂度为 排序序列长度,时间复杂度为 序列长度*log(序列长度)

qsort方法介绍:

1、qsort是一种排序函数,可以对多种数组数据类型进行排序(结构体、字符串、整型等)

2、其使用的排序方法为快速排序,且使用时需要包含<stdlib.h>的头文件

3、函数声明:void qsort (void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2));

void* base: 需要排序的数组地址

size_t num: 需要排序的数组元素个数

size_t size: 需要排序的单个数组元素大小

int (*compar)(const void* p1, const void* p2):  排序判断函数,自定义此函数来决定升序还是降序(*p1 - *p2 升序,*p2 - *p1降序)

java实现:

java">public static void merge(int[] nums1, int m, int[] nums2, int n) {for (int i = 0; i < n; i++) {nums1[m+i] = nums2[i];}Arrays.sort(nums1);
}

和C实现基本类似,Arrays.sort()方法更简洁一些;

Arrays.sort()方法介绍:

1、Arrays.sort()是JAVA提供的静态方法,用于对数组进行排序(默认升序),位于java.util.Arrays类中,使用前需import

2、对基础数据类型,使用双轴快速排序;对对象类型,使用TimSort(归并排序的改进版)

3、范围排序时需确保索引合法;对象排序需保证实现Comparable或提供自定义比较器


优解思路&解法二(C) -- 双指针

方法一虽然ok,但没有利用nums1和nums2已经被排序的性质,我们可以将nums1和nums2看作两个队列,每次将两个队列头部比较小的数字放到nums3中(需额外开辟)

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int p1 = 0;int p2 = 0;int* nums3 = (int *)malloc((m+n)*sizeof(int));int temp;while (p1 < m || p2 < n) {if (p1 == m) {temp = nums2[p2++];}else if (p2 == n) {temp = nums1[p1++];}else if (nums1[p1] < nums2[p2]) {temp = nums1[p1++];}else {temp = nums2[p2++];}nums3[p2 + p1 - 1] = temp;}for (int i = 0; i < m + n; i++) {nums1[i] = nums3[i];}free(nums3);
}

时间复杂度:O(m+n)  指针移动单调递增,最多移动m+n次,因此时间复杂度为O(m+n)

空间复杂度:O(m+n)  需要建立长度为m+n的中间数组nums3

注意点:if else的顺序要注意,如果else if (nums1[p1] < nums2[p2])逻辑在最前时,会出现当nums1[p1]==0时,条件会一直满足,p1一直++导致越界

java实现:

java">public static void merge(int[] nums1, int m, int[] nums2, int n) {int p1 = 0;int p2 = 0;int temp = 0;int[] nums3 = new int[m+n];while (p1 < m || p2 < n) {if (p1 == m) {temp = nums2[p2++];} else if (p2 == n) {temp = nums1[p1++];} else if (nums1[p1] < nums2[p2]) {temp = nums1[p1++];} else {temp = nums2[p2++];}nums3[p1+p2-1] = temp;}for (int i = 0; i < m+n; i++) {nums1[i] = nums3[i];}}

优解思路&解法三(C)-- 逆向双指针

方法二也是ok的,但额外开辟了m+n的空间;已知nums1的空间足够容纳nums2中的元素,且nums1和nums2都是有序数组,nums1中最大的数为nums1[m-1],nums2中最大的数为nums2[n-1],我们可以逆向比较两个数组的最大值,放入nums1[m+n-1]的位置中,以此递减;

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int p1 = m - 1;int p2 = n - 1;int p3 = m + n - 1;int temp = 0;while (p1 > -1 || p2 > -1) {if (p1 == -1) {temp = nums2[p2--];}else if (p2 == -1) {temp = nums1[p1--];}else if (nums1[p1] < nums2[p2]) {temp = nums2[p2--];}else {temp = nums1[p1--];}nums1[p3--] = temp;}
}

时间复杂度:O(m+n) 指针移动单调递减,最多移动m+n次,因此时间复杂度为O(m+n)

空间复杂度:直接对数组nums1原地修改,不需要额外空间

java实现:

java">public static void merge(int[] nums1, int m, int[] nums2, int n) {int p1 = m - 1;int p2 = n - 1;int temp = 0;int p3 = m + n - 1;while (p1 > -1 || p2 > -1) {if (p1 == -1) {temp = nums2[p2--];} else if (p2 == -1) {temp = nums1[p1--];} else if (nums1[p1] < nums2[p2]) {temp = nums2[p2--];} else {temp = nums1[p1--];}nums1[p3--] = temp;}		
}


http://www.ppmy.cn/ops/142175.html

相关文章

测试脚本并发多进程:pytest-xdist用法

参考&#xff1a;https://www.cnblogs.com/poloyy/p/12694861.html pytest-xdist详解&#xff1a; https://www.cnblogs.com/poloyy/p/14708825.html 总 https://www.cnblogs.com/poloyy/category/1690628.html

【蓝桥杯选拔赛真题94】Scratch巡逻的直升机 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析

目录 scratch巡逻的直升机 一、题目要求 编程实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、python资料 sc…

架构实践03-高可用架构模式

零、文章目录 架构实践03-高可用架构模式 1、CAP 定理 &#xff08;1&#xff09;CAP 定理的背景 提出者&#xff1a;加州大学伯克利分校的埃里克布鲁尔&#xff08;Eric Brewer&#xff09;在2000年ACM PODC会议上提出。证明者&#xff1a;麻省理工学院的赛斯吉尔伯特&…

大模型qiming面试内容整理-深度模型特定问题

在面试中涉及深度学习模型的特定问题时,面试官通常会关注你对深度学习技术的深入理解、如何应对模型训练中的常见挑战以及如何优化模型以适应不同的任务。以下是一些可能会涉及的深度模型特定问题,这些问题涵盖了深度学习模型的各个方面,包括模型架构、训练问题、优化技术以…

OpenCV--图像查找

OpenCV--图像查找 代码和笔记 代码和笔记 import cv2 import numpy as np""" 图像查找--特征匹配的应用&#xff0c;通过特征匹配和单应性矩阵 单应性变换&#xff1a;描述物体在世界坐标系&#xff08;原图&#xff09;和像素坐标系&#xff08;对比图&#x…

QILSTE H8-316QSY高亮黄光LED灯珠 发光二极管LED

在电子元件的多样化领域中&#xff0c;H8-316QSY型号的LED以其特定的技术参数&#xff0c;成为了一个不可忽视的选择。本文将通过增加文本的复杂性和句子的长短变化&#xff0c;来探讨这款LED的关键技术参数&#xff0c;为技术专家和工程师提供一个深入的参考。 首先&#xff…

数据结构——栈的模拟实现

大家好&#xff0c;今天我要介绍一下数据结构中的一个经典结构——栈。 一&#xff1a;栈的介绍 与顺序表和单链表不同的是&#xff1a; 顺序表和单链表都可以在头部和尾部插入和删除数据&#xff0c;但是栈的结构就锁死了&#xff08;栈的底部是堵死的&#xff09;栈只能从…

API成批分配漏洞修复

使用jackson增加全局序列化方式&#xff0c;校验所有接口入参&#xff0c;判断是否包含多余入参&#xff0c;比如原本后端接收的入参为: { ​"name":"张三", ​"age":"22", ​"high":"183" ​ } 如果前端传参多…