LintCode 解题记录 7.11 ~ 7.16

7.1~7.10号去南京玩了,所以没有刷题。现在回来了,题目继续搞起吧~

LintCode Median of Two Sorted Array

HARD题,没做出来。
看完网上的思路来总结一下:
这题可以转换为topK问题来解决,已知有序数组A和数组B,其合并后的中位数就是求其第k(k = (A.size+B.size)/2 )小数的问题。我们可以分别在数组A和B中考虑第k/2数,即A[k/2-1]和B[k/2-1],那么就可以分为三种情况:
1)A[k/2-1] < B[k/2-1],那么小于A[k/2-1]的数最多就有A[0],A[1],..A[k/2-2]和B[0],B[1],…,B[k/2-2],即k-2个数,也就是A[k/2-1]至多是k-1小的数,永远不可能是第k小的数。所以A[0],..,A[k/2-1]这些数都可以丢弃,那么原问题就变成了在新的两个有序数组中求第k/2小数。
2)A[k/2-1] > B[k/2-1],同样可以跟上面考虑。
3)如果两者相等,那么A[k/2-1]就是想要的第k小的数。
那么代码如下:

    double findMedianSortedArrays(vector<int> A, vector<int> B) {
        // write your code here
       int total = A.size()+B.size();
       if (total % 2 == 1) {
           return findKth(A, 0, B, 0, total/2+1);
       } else {
           return (findKth(A, 0, B, 0, total/2)+findKth(A, 0, B, 0, total/2+1))/2;
       }
    }

    double findKth(vector<int> A, int i, vector<int> B, int j, int k) { //i和j代表数组A和B的起始位置
        //首先确保A的size小于B的size,如果不是,则交换两个数组即可。
        if (A.size()-i > B.size()-j) return findKth(B, j, A, i, k);
        //如果A数组为空,那么就返回B数组的第k小数
        if (A.size() == i) return B[j+k-1];
        //k == 1是递归终止的条件,即分治法最终截止的条件。
        if (k == 1) return min(A[i], B[j]);
        //pa代表的是数组A的第k/2小数,如果A.size < k/2就取最后一个数,pb同理
        int pa = min(i+k/2, int(A.size())), pb = min(j+k/2, int(B.size()));
        //按照上述讨论的三种情况,分别递归
        if (A[pa-1] < B[pb-1])
            return findKth(A, pa, B, j, k-pa+i);//舍弃A[i:pa-1]的数,则从第k小变成了第k-pa+i小
        else if (A[pa-1] > B[pb-1])
            return findKth(A, i, B, pb, k-pb+j);
        else
            return A[pa-1];
    }

这个代码自己都看着晕乎了,简化一下:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        return (findKth(nums1, nums2, (m + n + 1) / 2) + findKth(nums1, nums2, (m + n + 2) / 2)) / 2.0;
    }
    int findKth(vector<int> nums1, vector<int> nums2, int k) {
        int m = nums1.size(), n = nums2.size();
        if (m > n) return findKth(nums2, nums1, k);
        if (m == 0) return nums2[k - 1];
        if (k == 1) return min(nums1[0], nums2[0]);
        int i = min(m, k / 2), j = min(n, k / 2);
        if (nums1[i - 1] > nums2[j - 1]) {
            return findKth(nums1, vector<int>(nums2.begin() + j, nums2.end()), k - j);
        } else {
            return findKth(vector<int>(nums1.begin() + i, nums1.end()), nums2, k - i);
        }
        return 0;
    }
};

参考链接:http://www.cnblogs.com/grandyang/p/4465932.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值