算法的时间复杂度应该为 O(log (m+n))
如何分析时间复杂度 https://blog.csdn.net/qq_41523096/article/details/82142747
T(n) = 5logn,执行次数是对数的。
void eat2(int n){
for(int i=1; i<n; i*=2){
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("吃一半面包");
}
}
典型的logn 就是二分查找
O(logn)的本质:输入规模翻倍,操作次数只增加一
考虑问题不全面 应该先考虑到其中一个数组为空的情况
其次没有考虑到nums2数组填完以后要将剩余的nums1的数字填进去
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int temp[]=new int [nums1.length+nums2.length];
int index=0;
int interB;
int interE=0;
//1 2 4 5 和 2 3 7 9
//右边2通过二分查找找到左边的相等或者小于最接近的x
//将左边小于这个x的全部放进去
//然后右边加一
//重复时 左边从上一个x1的位置到查到的x2的位置之间
if(nums2.length==0){
temp=nums1;
}else if(nums1.length==0){
temp=nums2;
}else{
for(int j=0;j<nums2.length;j++){
if(j==0){
interB=0;
}else{
interB=binarySearch(nums1,nums2[j-1]);
}
interE=binarySearch(nums1,nums2[j]);
for(int i=interB;i<interE;i++){
temp[index]=nums1[i];
index++;
}
temp[index]=nums2[j];
index++;
}
for(int m=interE;m<nums1.length;m++){
temp[index]=nums1[m];
index++;
}
}
if(temp.length%2==0){
return (double)(temp[(temp.length-1)/2]+temp[(temp.length-1)/2+1])/2;
}else{
return temp[(temp.length-1)/2];
}
}
public int binarySearch(int[] nums,int target){
int left=0, right=nums.length-1;
while(left<=right){
int middle=left+(right-left)/2;
if(nums[middle]>target){
//在左边
right=middle-1;
}else if(nums[middle]<target){
//在右边
left=middle+1;
}else{
return middle;
}
}
return left;
}
}
执行用时太多 虽然提交通过 还需改进算法。
看到了log(m+n) 但是没有理解对 依然是使用二分查找来实现两个数组合并加排序
并不一定比直接合并加快排来的块
新解法
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
//num1为较短数组
if(nums1.length>nums2.length){
int temp[] =nums1;
nums1=nums2;
nums2=temp;
}
//条件一 左边的数和右边的数相等或者多一个中位数
int m=nums1.length;
int n=nums2.length;
int totalLeft=(m+n+1)/2;
//这条线左边的数的个数为(m+n+1)/2
//假定奇数数列的中位数归到左边
//计算出一个数列的中位数后用公式计算的出另一个数列的中位数
int left=0;
int right=m;
//条件二
//nums1[i-1]<=nums2[j]&&nums2[j-1]<n=ums1[i]
//考虑没有达成的处理办法 给条件取反
//nums1[i-1]>nums2[j]||nums2[j-1]>nums1[i]
//所以只处理一种情况就行
while(left<right){
int i=left+(right-left+1)/2;
int j=totalLeft-i;
if(nums1[i-1]>nums2[j]){
right=i-1;
}else{
left=i;
}
}
int i=left;
int j=totalLeft-i;
int nums1LeftMax= i==0 ? Integer.MIN_VALUE :nums1[i-1];
int nums1RightMin= i==m ? Integer.MAX_VALUE :nums1[i];
int nums2LeftMax= j==0 ? Integer.MIN_VALUE :nums2[j-1];
int nums2LeftMin= j==n ? Integer.MAX_VALUE :nums2[j];
if((m+n)%2==0){
return (double)(Math.max(nums1LeftMax,nums2LeftMax)+Math.min(nums1RightMin,nums2LeftMin))/2;
}else{
return Math.max(nums1LeftMax,nums2LeftMax);
}
}
}