https://leetcode.com/problems/median-of-two-sorted-arrays/
非常不错的题。
最不济是可以想到log(m)*log(n)的做法的:
在第一个数组二分答案,然后再另一个数组二分,当然也有一些边界问题处理
一直盯着log(n+m) 不知道怎么回事,因为貌似一合并就会O(n+m)
然后看了题解,,,,,
把问题转化为findKthNum , 每次去掉一部分区间:
//
// main.cpp
// Search Insert Position
//
// Created by zengwei on 15/12/22.
// Copyright (c) 2015年 zengwei. All rights reserved.
//
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/*class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int pos = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
return pos;
}
};*/
/*class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int low = 0, high = (int)nums.size()-1;
if(nums[high] < target ) return (int)nums.size();
if(nums.size() && nums[0] >= target) return 0;
int ans = 0;
while (low < high) {
int mid = (low+high) >> 1;
ans = mid;
if(nums[mid] == target) {
ans = mid;
break;
}
else {
if(nums[mid] > target) {
high = mid-1;
} else {
low = mid+1;
ans = low;
}
}
}
return ans;
}
};*/
/*class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int low = 0, high = nums.size()-1;
while (low <= high) { //here <= or = is important.
int mid = (low+high) >> 1;
if(nums[mid] == target) {
low = mid;
break;
}
else {
if(nums[mid] > target) {
high = mid-1;
} else {
low = mid+1;
}
}
}
return low; // here low=high+1, it means low point to the value that a little bigger than ..
// and if there is a target in the array, it will break the loop
}
};*/
/*class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//if()
int pos1 = lower_bound(nums1.begin(), nums1.end(), nums1.size()/2) - nums1.begin();
int len1=nums1.size(),len2=nums2.size();
int cnt = len1+len2;
int loop = 1;
int tar , ans;
while(cnt != (len1+len2)/2 &&
(len1|len2)) {
if(loop%2) {
if(loop == 1) tar = nums1[len1-1];
else tar = nums1[len1/2];
} else {
tar = nums2[len2/2];
}
cnt = lower_bound(nums1.begin(), nums1.begin()+len1, tar) - nums1.begin()+1;
cnt += lower_bound(nums2.begin(), nums2.begin()+len2, tar) - nums2.begin();
if(loop%2) {
len1 /= 2;
ans = nums1[len1];
} else {
len2 /= 2;
ans = nums2[len2];
}
loop++;
}
return ans;
}
};*/
/*
*/
class Solution {
public:
double findKthNum(vector<int>& nums1, vector<int>& nums2, int k) {
if(nums1.size() > nums2.size()) return findKthNum(nums2, nums1, k);
if(nums1.size() == 0)return nums2[k-1];
if(k == 1)return min(nums1[0], nums2[0]);
int ptr1 = min((int)nums1.size(), k/2), ptr2 = k-ptr1;
if(nums1[ptr1-1] < nums2[ptr2-1]) {
vector<int> vec (nums1.begin()+ptr1,nums1.end());
return findKthNum(vec, nums2, k-ptr1);
} else if(nums1[ptr1-1] > nums2[ptr2-1]) {
vector<int> vec (nums2.begin()+ptr2, nums2.end());
return findKthNum(nums1, vec, k-ptr2);
} else {
return nums1[ptr1-1];
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size();
if(nums1.size() == 0) {
return nums2.size()%2 ? nums2[nums2.size()/2] :(nums2[(nums2.size()/2)] + nums2[nums2.size()/2-1])/2.0;
}
if(nums2.size() == 0) {
return nums1.size()%2 ? nums1[nums1.size()/2] : (nums1[nums1.size()/2] + nums1[nums1.size()/2-1])/2.0;
}
if(total%2) {
return findKthNum(nums1, nums2, (total/2)+1);
} else {
return (findKthNum(nums1, nums2, total/2) + findKthNum(nums1, nums2, total/2+1))*1.0/2.0;
}
}
};
int main(int argc, const char * argv[]) {
int n, m,in;
while(cin >> n >> m) {
vector <int> nvec;
vector <int> mvec;
for(int i=0;i<n;i++) {
cin >> in;
nvec.push_back(in);
}
for(int i=0;i<m;i++) {
cin >> in;
mvec.push_back(in);
}
Solution s;
cout << s.findMedianSortedArrays(nvec, mvec) << endl;
}
return 0;
}
class Solution {
public:
// double findKth(vector<int>& nums1, int l1, int r1, vector<int>& nums2, int l2, int r2, int k) {
// if(r1 < l1) {
// int pos = k - r1 - r2;
// return nums2[pos];
// }
// if(r2 < l2) {
// int pos = k - r1 - r2;
// return nums1[pos];
// }
// if(k == 0) {
// if(nums1[l1] < nums2[l2]) return nums1[l1];
// else return nums2[l2];
// }
// // k > 0
// if(l1 + l2 == k) return nums1[l1] < nums2[l2] ? nums1[l1]:nums2[l2];
// // k - l1 - l2
// int mid = (k - l1 - l2) / 2;
// int lp, lv, rp, rv;
// if(l1 + mid > r1) {
// lp = r1;
// lv = nums1[r1];
// } else {
// lp = l1 + mid;
// lv = nums1[lp];
// }
// if(l2+mid > r2) {
// rp = r2;
// rv = nums2[rp];
// } else {
// rp = l2+mid;
// rv = nums2[rp];
// }
// if(lv < rv) {
// return findKth(nums1, lp+1, r1, nums2, l2, r2, k);
// } else {
// return findKth(nums1, l1, r1, nums2, rp+1, r2, k);
// }
// }
double findKth(vector<int>& nums1, int l1, int r1, vector<int>& nums2, int l2, int r2, int k) {
if(r1 - l1 > r2 - l2) return findKth(nums2, l2, r2, nums1, l1, r1, k);
// int pos = k - r1-1 ;
if(r1 - l1 + 1 == 0) {
return nums2[l2 + k-1]; // check
}
if(k == 1) return min(nums1[l1], nums2[l2]);
int idx1 = min(r1-l1+1, k/2 )-1, idx2 = k - min(r1-l1+1, k/2 ) - 1 ;
// int idx1 = min(r1-l1+1, k/2 )-1, idx2 = min(r2-r1+1, k/2)-1 ;
if(nums1[l1 + idx1] <= nums2[l2 + idx2]) {
return findKth(
nums1, l1 + idx1+1, r1, nums2, l2, r2, k-idx1-1
);
} else {
return findKth(
nums1, l1, r1, nums2, l2 + idx2+1, r2, k-idx2-1
);
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int sz = nums1.size() + nums2.size();
// if(nums1.size() < nums2.size() ) swap(nums1, nums2);
// if(nums2.size() == 0) {
// if(nums1.size() == 1) return nums1[0];
// return nums1.size()%2 ? nums1[sz/2-1] : (nums1[sz/2]);
// }
if(sz%2) {
return findKth(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, (sz)/2+1);
} else {
// double a = findKth(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, (sz)/2);
// double b = findKth(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, (sz)/2+1) ;
// // cout << "a:" << a << " b:" << b << endl;
// return (double)(a+b)/2;
return ( findKth(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, sz/2) + findKth(nums1, 0, nums1.size()-1, nums2, 0, nums2.size()-1, sz/2+1) )/2;
}
}
};