归并
概念
何谓归并?归并其实是两个步骤,一个是归,还有一个是并。归是两个和两个以上的有序文件组成一起的过程,而并,就是将这些分组合并成一个新的有序文件。
例题分析
力扣之中,寻找两个正序数组的中位数,题目是这样的:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
这题的思路其实很简单,先进行排序,再寻找中位数即可,有很多种办法都能将他们进行排序,这里我采用归并的方法。
我们先来看看初步排序的过程,我假设数组nums1空间为5,数组nums2空间为6,然后开辟新的num辅助数组空间,来当做归并之后的数组。
基本思路
我们举例分析,将nums1 = {3, 5, 7, 8, 10}, nums2 = {4, 6, 8, 9, 11, 12}. 首先,将nums1的第一个值3与nums2的第一个值5进行比较,那么较小值3,将会复制到num数组中,此时,nums1的下标索引自增指向5,nums2下标索引不变化,num的下标在每一次赋值操作之后都需要索引加一。而后,继续按照这样的操作,另外虽然nums[3]与nums[2]的值相同,但是统一先让nums1数组的下标索引自增。直到有一个数组全部遍历完,也就是当nums1的下标索引超过数组的长度时,让另外一个数组的值复制到nums中,最终完成归并。然后找出中位数。
图解
具体代码
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int l1 = nums1.length;
int l2 = nums2.length;
int[] num = new int[l1 + l2];
// 第一个数组索引位置
int i = 0;
// 第二个数组索引位置
int j = 0;
// 定义的num数组索引位置
int k = 0;
//两个数组都有值时进行比较,之后向新定义的数组中赋值
/*while(i < l1 && j < l2){
if(nums1[i] < nums2[j]){
num[k] = nums1[i++];
}else{
num[k] = nums2[j++];
}
k++;
}*/
for(i=0;i<l1&&j<l2;k++)
{
if(nums1[i] < nums2[j]){
num[k] = nums1[i++];
}else{
num[k] = nums2[j++];
}
}
// 第二个数组中元素已遍历完成,把第一个数组中剩余元素放到新建数组中
if(i < l1){
for (int a = i; a<l1; a++){
num[k++] = nums1[a];
}
}else{
for (int a = j; a<l2; a++){
num[k++] = nums2[a];
}
}
// 上面的代码其实就是合并两个有序数组,下面的代码就是找到中间位置,然后取出元素
// 取余,因为如果余数为1,则直接取中间的那个元素,如果余数为0,需要取两个元素然后除以2
int y = num.length % 2;
// 中间元素位置的索引值
int c = num.length / 2;
if(y == 1){
return num[c];
}else{
return (double)(num[c] + num[c - 1])/2;
}
}
}
代码分析
简单来说,代码分为两个阶段,一个是归并阶段,还有一个是寻找中位数的阶段。
归并阶段
归并阶段就是上述思想实现,期间采用for循环或者while循环都可以实现。
寻找中位数
寻找中位数,也需要判断单双。这个时候需要我们的求余数法则,取余,如果余数为1,则直接取中间的那个元素,如果余数为0,需要取两个元素然后除以2。
总结
每日力扣,感受代码,学习方法,总结经验。
希望对大家的学习有所帮助,谢谢!