寻找两个数组的中位数
package com.wb.magic.leetcode.array;
import java.util.Arrays;
/**
* 给你两个已经从小到大排好序的数组,请你找出这两个数组合并并排序后的中位数。
*
* 你给出的算法的时间复杂度应该为 O(log (m+n)) 。
*/
public class MiddleNumber {
//方法一双层for循环排序后招中位数
//方法二 复制数组到一个数组中再排序找中位数
//方法三
public static void main(String[] args) {
int[] num1 ={1,3};
int[] num2 = {2,4};
System.out.println(method1(num1, num2));
System.out.println(method2(num1, num2));
System.out.println(method3(num1, num2));
// System.out.println(14&1);
}
//合并排序后再找中位数
public static double method1(int []num1,int [] num2){
int[] target=new int[num1.length+num2.length];
System.arraycopy(num1,0,target,0,num1.length);
for (int i = 0; i < num2.length; i++) {
target[num1.length+i]=num2[i];
}
Arrays.sort(target);
int nums=target[(num1.length+num2.length)/2];
if((target.length&1)==1){
return nums;
}else {
return (nums+target[(num1.length+num2.length)/2-1])/2.0;
}
}
//归并方式:直接找中位数,两数组从前往后比较,两指针移动,谁小谁移动
public static double method2(int []num1,int [] num2){
int m=num1.length;
int n=num2.length;
//无论两数组长度之和是奇数还是偶数,都需要(m+n)/2+1次
int len=m+n;
//返回记录数
int left=0;
int right=0;
//两数组指针
int num1Next=0;
int num2Next=0;
for (int i = 0; i <= (m+n)/2; i++) {
//对于偶数保存上一次记录数字
left=right;
//避免num2数组指针越界,||来限制后面就不用执行(使用||运算符排除部分可能,这个可能位于||运算符左边)
if(num1Nextn||num1[num1Next]int[]num1={2,5,8};
* * int[]num2={6,7,8,9,10}; 排除一个数字 k为2
* * ->int[]num1={5,8};
* * * int[]num2={6,7,8,9,10}; 排除一个数字 k为1
* * ->int[]num1={5,8};
* * * int[]num2={6,7,8,9,10};
* k为1直接得到想要的值
* //如国两数为奇数,中位数必是奇数,定义找到第k大的数字,k为1时候就是想要数字(n+m+1)/2
*//如果是偶数的话,中位数就是(n+m+1)/2 (n+m+2)/2 两个数之间的中位数
*
//二分法查找中位数位置
public static int getKth(int[] nums1,int start1,int end1,int[]nums2,int start2,int end2,int k){
int size1=end1-start1+1;
int size2=end2-start2+1;
if(k==1){
return Math.min(nums1[start1],nums2[start2]);
}
if(size1==0){
return nums2[start2+k-1];
}
int pos1=start1+Math.min(size1,k/2)-1;
int pos2=start2+Math.min(size2,k/2)-1;
if(nums1[pos1]>nums2[pos2]){
return getKth(nums1,start1,end1,nums2,pos2+1,end2,k-(pos2-start2+1));
}else {
return getKth(nums1,pos1+1,end1,nums2,start2,end2,k-(pos1-start1+1));
}
}
}
package com.wb.magic.leetcode.array;
import java.util.Arrays;
public class MiddleNumber {
public static void main(String[] args) {
int[] num1 ={1,3};
int[] num2 = {2,4};
System.out.println(method1(num1, num2));
System.out.println(method2(num1, num2));
System.out.println(method3(num1, num2));
}
public static double method1(int []num1,int [] num2){
int[] target=new int[num1.length+num2.length];
System.arraycopy(num1,0,target,0,num1.length);
for (int i = 0; i < num2.length; i++) {
target[num1.length+i]=num2[i];
}
Arrays.sort(target);
int nums=target[(num1.length+num2.length)/2];
if((target.length&1)==1){
return nums;
}else {
return (nums+target[(num1.length+num2.length)/2-1])/2.0;
}
}
public static double method2(int []num1,int [] num2){
int m=num1.length;
int n=num2.length;
int len=m+n;
int left=0;
int right=0;
int num1Next=0;
int num2Next=0;
for (int i = 0; i <= (m+n)/2; i++) {
left=right;
if(num1Next<m&&(num2Next>n||num1[num1Next]<num2[num2Next])){
right=num1[num1Next++];
}else {
right=num2[num2Next++];
}
}
if((len&1)==0){
return (left+right)/2.0;
}else {
return right;
}
}
public static double method3(int []num1,int [] num2){
int ans1=getKth(num1,0,num1.length-1,num2,0,num2.length-1,(num1.length+num2.length+1)/2);
int ans2=getKth(num1,0,num1.length-1,num2,0,num2.length-1,(num1.length+num2.length+2)/2);
return (ans1+ans2)/2.0;
}
public static int getKth(int[] nums1,int start1,int end1,int[]nums2,int start2,int end2,int k){
int size1=end1-start1+1;
int size2=end2-start2+1;
if(k==1){
return Math.min(nums1[start1],nums2[start2]);
}
if(size1==0){
return nums2[start2+k-1];
}
int pos1=start1+Math.min(size1,k/2)-1;
int pos2=start2+Math.min(size2,k/2)-1;
if(nums1[pos1]>nums2[pos2]){
return getKth(nums1,start1,end1,nums2,pos2+1,end2,k-(pos2-start2+1));
}else {
return getKth(nums1,pos1+1,end1,nums2,start2,end2,k-(pos1-start1+1));
}
}
}