c++- 两个正序数组的中位数

#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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值