码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode 4 Median of Two Sorted Arrays

时间:2020-02-12 12:51:16      阅读:52      评论:0      收藏:0      [点我收藏+]

标签:pop   erase   通过   for   open   提前   array   private   oss   

这道题要求两个有序数组,找出中间位置的平均值;

解题思路:

1、取A数组的中间位置mid的值key,去B数组中查找最靠近key且小于等于key的位置index;

2、将原数组切成三段,index和mid之前数组的为新的left数组;right1跟right2为新的right数组;mid到right1和index到right2为新的middle数组;

3、通过判断数组的长度,知道在哪个数组段;当运气好找到中间位置的时候,则可提前给出结果;

4、将切割完的数组,数组长度比较长的作为A数组,比较短的作为B数组继续执行1操作;

5、当数组长度小于等于4的时候结束;直接排序给结果;

 

这里用到了滚动数组的思想,让4更容易操作;

技术图片
class Solution {
private:
    int FirstLower(const int* nums, int left, int right, int key) {
        int mid = left;
        while (left < right) {
            if (left + 1 == right) {
                if (nums[left] > key)
                    return -1;
                return left;
            }
            mid = (left + right) >> 1;
            if (nums[mid] > key)
                right = mid;
            else
                left = mid;
        }
        return -1;
    }

public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int* nums[2];
        nums[0] = nums1.data();
        nums[1] = nums2.data();
        int row = 0;
        int left[2] = {0, 0};
        int right[2] = {(int)nums1.size(), (int)nums2.size()};
        int right_static[2] = {(int)nums1.size(), (int)nums2.size()};
        int total_static = right[0] + right[1];

        for (int i = 0; i < 2; ++i) {
            if (right[i] == 0) {
                if (1 == right[1-i] % 2)
                    return nums[1-i][right[1-i]/2];
                return (nums[1-i][right[1-i]/2] + nums[1-i][right[1-i]/2-1]) / 2.0;
            }
        }
        
        int need = 0;
        int c0 = 0, c1 = 0;
        while (true) {
            c0 = 0;
            c1 = 0;
            if (left[row] < right_static[row])
                c0 = right[row] - left[row];
            if (left[1-row] < right_static[1-row])
                c1 = right[1-row] - left[1-row];
            if (c0 + c1 <= 4)
                break;
            if (c0 <= c1) {
                row = 1-row;
            }
            
            int mid = (right[row] + left[row]) >> 1;
            int index1_row = FirstLower(nums[1-row], left[1-row], right[1-row], nums[row][mid]);
            if (index1_row >= 0)
                ++index1_row;
            
            int may_left = mid + left[1-row];
            int may_right = total_static - right[row] - right[1-row];
            int may_middle = right[row] - mid + right[1-row] - left[1-row];
            
            if (index1_row >= 0) {
                may_left += index1_row - left[1-row];
                may_middle -= index1_row - left[1-row];
            }
            
            if (may_left > may_right) {
                if (may_left - may_right > may_middle) {
                    right[row] = mid;
                    if (index1_row == -1)
                        right[1-row] = left[1-row];
                    else
                        right[1-row] = index1_row;
                } else if (may_left - may_right < may_middle) {
                    left[row] = mid;
                    if (index1_row >= 0)
                        left[1-row] = index1_row;
                } else {
                    if (left[1-row] < right[1-row]) {
                        if (index1_row == -1) {
                            right[1-row] = left[1-row] + 1;
                        } else {
                            left[1-row] = index1_row - 1;
                            if (index1_row + 1 <= right[1-row])
                                right[1-row] = index1_row+1;
                        }
                    } else {
                        left[1-row] = right[1-row];
                    }
                    right[row] = mid + 1;
                    if (left[row] < mid)
                        left[row] = mid - 1;
                    else
                        left[row] = mid;
                }
            } else {
                if (may_right - may_left < may_middle) {
                    left[row] = mid;
                    if (index1_row >= 0)
                        left[1-row] = index1_row;
                } else {
                    std::cout << "impossible\n";
                }
            }

            need = total_static - right[row] - right[1-row] - left[row] - left[1-row];
        }
        
        vector<int> result;
        for (int i = 0; i < 2; ++i) {
            for (int j = left[i]; j < right[i]; ++j) {
                if (0 <= j && j < right_static[i])
                    result.push_back(nums[i][j]);
            }
        }
        sort(result.begin(), result.end());
        while (need > 0) {
            result.erase(result.begin());
            --need;
        }
        while (need < 0) {
            result.pop_back();
            ++need;
        }
        
        if (result.size() % 2 == 0) {
            if (result.size() == 2)
                return (result[0] + result[1]) / 2.0;
            else if (result.size() == 4)
                return (result[1] + result[2] ) / 2.0;
        } else {
            if (result.size() == 1)
                return result[0]/ 1.0;
            else if (result.size() == 3)
                return result[1] / 1.0;
        }
        
        return 0.0;
    }
};
View Code

代码中的输出impossilbe的那个判断条件,是因为当右边的数组r大于左边l加中间m的时候,则上一轮的切割结果一定比当前的切割结果差距更大;那么目标位置应当到右边去查找;则与此轮的查找位置相矛盾;

leetcode 4 Median of Two Sorted Arrays

标签:pop   erase   通过   for   open   提前   array   private   oss   

原文地址:https://www.cnblogs.com/czwlinux/p/12298378.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!