#include <iostream>
#include <utility>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <fstream>
using namespace std;
// 直接调试去掉下面的注释, 然后把 dir改成绝对路径
#define TEST
#ifdef TEST
// 修改这里可以改成绝对路径用 ide 直接调试
string dir = "/Users/nichao/Code/c++/untitled1/";
string inputFile = dir + "input.txt";
string outputFile = dir + "output.txt";
string expectFile = dir + "expect.txt";
ifstream in(inputFile);
ofstream out(outputFile);
ifstream output(outputFile);
ifstream expect(expectFile);
string emptyStr = "nullptr";
template<typename T, typename ...Args>
auto has_begin(int) -> decltype(declval<T>().begin(declval<Args>...), true_type{});
template<typename T, typename ...Args>
false_type has_begin(...);
template<typename T, typename ...Args>
using beginable = typename std::is_same<decltype(has_begin<T>(0)), true_type>::type;
// 用于实现了 operator<<的对象
template<typename Obj, typename = typename enable_if<
!is_same<
true_type,
beginable<
typename decay<Obj>::type
>
>::value
>::type
>
auto writeToFile(Obj &&r, bool end = true) -> decltype(void(out.operator<<(r))) {
out << r << " ";
if (end) {
out << endl;
}
}
// 容器都有 begin 方法
template<typename Container>
auto writeToFile(Container &&c, bool end = true) -> decltype(void(c.begin())) {
for (auto &&v : c) {
writeToFile(v, false);
}
if (end) {
out << endl;
}
}
// 用于数值退化成指针的情况
template<typename Arr, size_t N>
void writeToFile(Arr &&r, int n) {
for (int i = 0; i < n; ++i) {
out << r[n] << " ";
}
out << endl;
}
#else
istream &in = cin;
ostream &out = cout;
#endif
class Prepare {
public:
Prepare() {
prepare();
}
static void prepare() {
#ifdef TEST
if (!in.is_open()) {
cout << "empty input file" << endl;
exit(-1);
}
if (!expect.is_open()) {
cout << "empty expect file" << endl;
exit(-1);
}
#endif
}
};
class Check {
public:
~Check() {
// compare
#ifdef TEST
for (int i = 1; !output.eof(); ++i) {
if (output.eof()) {
break;
}
string l, r;
getline(output, l);
getline(expect, r);
while (!l.empty() && l.back() == ' ') {
l.pop_back();
}
while (!r.empty() && r.back() == ' ') {
r.pop_back();
}
if (l.empty() && r.empty()) {
break;
}
if (l == emptyStr) {
break;
}
if (l == r) {
cout << "case: " << i << " pass" << endl;
} else if (l != r) {
cout << "case: " << i << "wrong " << "output[" << l << "], while expect[" << r << "]" << endl;
continue;
}
}
#endif
}
};
static Prepare pre; // NOLINT
static Check check;
/// ===============提交的业务代码=============================
class Solution {
public:
int findMedianSortedArraysHelper(vector<int> &nums1, vector<int> &nums2, int rank) { // NOLINT
int m = nums1.size();
int n = nums2.size();
int l1 = 0, h1 = m - 1;
int l2 = 0, h2 = n - 1;
while (true) {
if (l1 > h1) {
return nums2[l2 + rank - 1];
}
if (l2 > h2) {
return nums1[l1 + rank - 1];
}
if (rank == 1) {
return min(nums1[l1], nums2[l2]);
}
int m1 = ((l1 + rank / 2 - 1) < h1) ? (l1 + rank / 2 - 1) : h1;
int m2 = ((l2 + rank / 2 - 1) < h2) ? (l2 + rank / 2 - 1) : h2;
if (nums1[m1] <= nums2[m2]) {
rank -= (m1 - l1 + 1);
l1 = m1 + 1;
} else if (nums1[m1] > nums2[m2]) {
rank -= (m2 - l2 + 1);
if (rank == 0) {
return nums2[m2];
}
l2 = m2 + 1;
}
}
}
double findMedianSortedArrays(vector<int> &nums) { // NOLINT
int m = nums.size();
if (m == 0) {
return 0;
}
if (m % 2 == 0) {
return (nums[m / 2] + nums[m / 2 - 1]) / 2.0;
}
return nums[m / 2];
}
double findMedianSortedArraysJointSorted(vector<int> &small, vector<int> &big) { // NOLINT
int m = small.size();
int n = big.size();
int total = m + n;
if (total % 2 == 0) {
if (m == n) {
return (small.back() + big.front()) / 2.0;
}
if (m > n) {
return (small[total / 2 - 1] + small[total / 2]) / 2.0;
}
return (big[total / 2 - m - 1] + big[total / 2 - m]) / 2.0;
} else {
if (m > n) {
return small[total / 2];
} else {
return big[total / 2 - m];
}
}
}
/* 1. 归并, 空间复杂度O(m + n), 时间 O(m + n)
* 2. 归并但不存, 预先算出目标下标, 时间 O(m + n)
* 3. 二分, 为什么想到二分,
* <1> 期望时间复杂度 O(log(m + n))
* <2> 数组相对有序
*
* */
double findMedianSortedArrays(vector<int> &nums1, vector<int> &nums2) {
int m = nums1.size();
int n = nums2.size();
// 边界
if (m == 0 && n == 0) {
return 0;
}
if (m == 0) {
return findMedianSortedArrays(nums2);
}
if (n == 0) {
return findMedianSortedArrays(nums1);
}
int total = m + n;
// 拼接有序
if (nums1.back() <= nums2.front()) {
return findMedianSortedArraysJointSorted(nums1, nums2);
}
if (nums1.front() >= nums2.back()) {
return findMedianSortedArraysJointSorted(nums2, nums1);
}
if (total % 2 == 0) {
int first = findMedianSortedArraysHelper(nums1, nums2, total / 2);
int second = findMedianSortedArraysHelper(nums1, nums2, total / 2 + 1);
return (first + second) / 2.0;
}
return findMedianSortedArraysHelper(nums1, nums2, total / 2 + 1);
}
};
#ifdef TEST
/// ===============测试代码=============================
int main() {
// 自定义读取输入 规定输入边界
int n;
in >> n;
while (n--) {
int m1, m2;
in >> m1 >> m2;
vector<int> nums1(m1);
vector<int> nums2(m2);
for (int i = 0; i < m1; i++) {
in >> nums1[i];
}
for (int i = 0; i < m2; i++) {
in >> nums2[i];
}
auto val = Solution{}.findMedianSortedArrays(nums1, nums2);
// 输出结果到 out
// 如
writeToFile(val);
}
}
#endif
c++- 两个正序数组的中位数
最新推荐文章于 2023-10-08 18:43:20 发布