给定两个大小为 m 和 n 的有序数组
nums1
和nums2
。请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设
nums1
和nums2
不会同时为空。示例 1:
nums1 = [1, 3] nums2 = [2] 则中位数是 2.0示例 2:
nums1 = [1, 2] nums2 = [3, 4] 则中位数是 (2 + 3)/2 = 2.5
这道题其实有点歧义,有人部分人认为是两个数组合并起来之后的中间值,有人认为是两数组合并之后中间哪一位或者那两位。
这道题是后者,找中间一位或者两位算平均值 当做其均值 。
比较简单,但是我用list合并两数组出现问题,每次add进去的都是1可能是list我还没搞明白
后来新建数组合并好很多,当然不想想了 思路知道就好了 贴一下别人代码 自己加的注释
int nums1length = nums1.length;
int nums2length = nums2.length;
int[] newnums= Arrays.copyOf(nums1, nums1length+nums2length);//数组扩容
System.arraycopy(nums2, 0, newnums, nums1length, nums2length);
//src - 源数组。
//srcPos - 源数组中的起始位置。
//dest - 目标数组。
//destPos - 目标数据中的起始位置。
//length - 要复制的数组元素的数量。
Arrays.sort(newnums);//将数组排序
if(newnums.length%2==1){//奇数,取中间
return newnums[newnums.length/2];
}
double num1=newnums[newnums.length/2-1];//取模为偶数时表示取中间两位
double num2=newnums[newnums.length/2];//但是下标是从0开始的所以除2表示中间上一位 再减一表示中间下一位
return (num1+num2)/2;
然后又分析了一波第一名的 也有点不是很懂为什么第一名的三个循环时间最少
int nums2length = nums2.length;
int[] r = new int[nums1.length + nums2length];//声明一个新的数组大小是两数组之和
int index = 0;
int j = 0;
for (int num : nums1) {//循环遍历第一个数组,将第一个数组里面的值全部塞到新数组中
while (j < nums2length && num > nums2[j]) {
r[index] = nums2[j];
//将第二个数组遍历,看是否比第一个数组当前值小,小就插入然后j++标记当前第二个塞入个数以及当前位置
j++;
index++;
}
r[index] = num;
index++;
}
//出来之后数组1一定是塞完了,所以数组2这时遍历如果还有就直接塞入就好 因为题目本身给出的就是有序数组
for (; j < nums2length; j++) {
r[index] = nums2[j];
index++;
}
//最后都一样 如果 模2余1表示中间值是1个 就是除2那个下标 余0表示中间值为两个 是除2 以及除2-1两个下标的平均值
int mi = r.length / 2;
return r.length % 2 == 1 ? r[mi] : (r[mi - 1] + r[mi]) / 2.0;
}
我想的是将数组2和数组1进行标记,每次给list塞入的时候判断两个数谁大,塞入之后对其标记的数自增更新标记,也减少很多循环次数。但是后来塞入list的值莫名其妙都是1了 就放弃了 反正思路一定是对的 。可能对list的原理不是很明白。