LeetCode: 4. 兩個排序數組的中位數

兩個排序數組的中位數

1、問題描述

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

​ 給定兩個大小爲 m 和 n 的有序數組 nums1nums2

請找出這兩個有序數組的中位數。要求算法的時間複雜度爲 O(log (m+n)) 。

示例 1:

nums1 = [1, 3]
nums2 = [2]

中位數是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位數是 (2 + 3)/2 = 2.5

2、解題思路

2.1 使用二分查找法

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
/*
*   基本思想:
*       每一次判斷,要找的是第k個數,如果在數組1中,第k/2個數比數組個數還要大,就是用最後一個數
        用兩個數組中的第k/2個數進行比較,如果第一個數組中的比第二個數組中的大,就能夠將第二個數組中前k/2個數排除在比較範圍之外
        這時候,要查找的的就不是第k個數,而是k-k/2個數,
*
*
*   left1:表示數組1的左邊界,數組下標
*   left2:表示數組2的左邊界,數組下標
*/
    int mid_loc;
    int pos1, pos2, left1 = 0, left2 = 0;
    // 奇偶判斷,奇數爲真,偶數爲假
    bool flag_odd_even = (nums1Size + nums2Size) % 2 == 0 ? false : true;
    bool found = false;
    double result;
    int result_pos;
    // 根據奇偶數,判斷中位數是第幾位數
    if (flag_odd_even) {
        //如果是奇數
        mid_loc = (nums1Size + nums2Size) / 2 + 1;
    } else {
        //如果是偶數
        mid_loc = (nums1Size + nums2Size) / 2;
    }

    // 判斷幾種特殊情況,可以直接返回結果
    if (nums1Size == 0 && nums2Size != 0 && nums2Size > mid_loc) {
        if (flag_odd_even) {
            result = nums2[mid_loc - 1];
        } else {
            result = (1.0 * nums2[mid_loc - 1] + nums2[mid_loc]) / 2;
        }
    } else if (nums2Size == 0 && nums1Size != 0 && nums1Size > mid_loc) {
        if (flag_odd_even) {
            result = nums1[mid_loc - 1];
        } else {
            result = (1.0 * nums1[mid_loc - 1] + nums1[mid_loc]) / 2;

        }
    } else {
        // 使用二分法,進行判斷
        while (!found) {

            pos1 = (mid_loc / 2) > (nums1Size - left1 - 1) ? nums1Size - 1 : (mid_loc / 2 + left1 - 1);
            pos2 = (mid_loc / 2) > (nums2Size - left2 - 1) ? nums2Size - 1 : (mid_loc / 2 + left2 - 1);

            if (nums1[pos1] >= nums2[pos2]) {
                // 如果第二個已經到了邊界, 在第一個數組中直接找到結果
                if (pos2 == (nums2Size - 1)) {
                    result_pos = mid_loc - (pos2 - left2 + 1) + left1 - 1;
                    //奇數
                    if (flag_odd_even) {

                        result = nums1[result_pos];
                    } else {
                        result = (1.0 * nums1[result_pos] + nums1[result_pos + 1]) / 2;
                    }
                    found = true;
                } else {

                    mid_loc -= (pos2 - left2 + 1);
                    left2 = pos2 + 1;
                }
            } else {
                // 如果第一個到了邊界,直接在第二個數組中找到結果
                if (pos1 == (nums1Size - 1)) {
                    result_pos = mid_loc - (pos1 - left1 + 1) + left2 - 1;
                    //奇數
                    if (flag_odd_even) {
                        result = nums2[result_pos];
                    } else {
                        result = (1.0 * nums2[result_pos] + nums2[result_pos + 1]) / 2;
                    }
                    found = true;

                } else {
                    mid_loc -= (pos1 - left1 + 1);
                    left1 = pos1 + 1;
                }
            }
            if (!found && mid_loc == 1) {

                if (nums1[left1] <= nums2[left2]) {
                    // 如果是奇數
                    if (flag_odd_even) {
                        result = nums1[left1];
                    } else {
                        // 第一個條件是邊界保護
                        if ((left1 < nums1Size - 1) && (nums1[left1 + 1] <= nums2[left2])) {
                            result = (1.0 * nums1[left1] + nums1[left1 + 1]) / 2;
                        } else {
                            result = (1.0 * nums1[left1] + nums2[left2]) / 2;
                        }
                    }
                } else {
                    if (flag_odd_even) {
                        result = nums2[left2];
                    } else {
                        // 第一個條件是邊界保護
                        if ((left2 < nums2Size - 1) && (nums2[left2 + 1] <= nums1[left1])) {
                            result = (1.0 * nums2[left2] + nums2[left2 + 1]) / 2;
                        } else {
                            result = (1.0 * nums2[left2] + nums1[left1]) / 2;

                        }
                    }

                }
                found = true;
            }
        }
    }
    return result;
}

2.2 緩衝數組法

​ 這個緩衝法就有點笨拙了,就類似於歸併排序裏面的,將兩個已排好序的數組合並起來,不過我們只需要其中一半即可,這樣就找到中位數了,這種辦法的好處就是思路非常清晰,簡單,但是會佔用額外的空間,並且速度不快;

double findMedianSortedArrays(int *nums1, int nums1Size, int *nums2, int nums2Size) {
/*
*   基本思想:
*
*
*/

    int buff_length = (nums1Size + nums2Size) / 2 + 1;
    int num = (int*)malloc(sizeof(int)*buff_length);
    bool flag_odd_even = (nums1Size + nums2Size) % 2 == 0 ? false : true;
    int i=0,j=0;
    int count = 0;
    double result;
    int temp_length = buff_length;
    while (temp_length-- ){
        if ((i <nums1Size && nums1[i] <= nums2[j]) || j>= nums2Size ){
            num[count++] = nums1[i];
            i++;
        }else if((j < nums2Size && nums2[j] <= nums1[i]) || i >= nums1Size){
            num[count++] = nums2[j];
            j++;
        }
    }

    if (flag_odd_even){
        result = num[buff_length-1];
    } else{
        result = (1.0 * num[buff_length-2] + num[buff_length-1])/2;
    }

    return result;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章