sponsored links

刷題LeetCode:4.尋找兩個正序陣列的中位數

題目連結:
力扣

題目描述

給定兩個大小分別為 m 和 n 的正序(從小到大)陣列 nums1 和 nums2。
請你找出並返回這兩個正序陣列的 中位數 。演算法的時間複雜度應該為 O(log (m+n))

題目分析

常規思路:
1.合併兩個陣列再排序,時間複雜度O(m+n),空間複雜度O(m+n)
2.歸併排序,時間複雜度O(m+n),空間複雜度O(1)
本題解題思路應該如何呢?

根據題目中時間複雜度,可以考慮採用二分查詢,這也是本題的難度所在。

假設兩個有序陣列分別是 A 和 B,兩陣列的總長度為 totalLength:

  • 兩陣列總長度(totalLength)為奇數:中位數下標(midIndex)=totalLength/2,中位數=下標midIndex所在數;
  • 兩陣列總長度(totalLength)為偶數,中位數下標有兩個 midIndex1,midIndex2, midIndex1=totalLength/2-1 ,midIndex2=totalLength/2,中位數=(下標midIndex1所在數+下標midIndex2所在數)/2;

注意:midIndex,為兩數組合並後的下標,並不是真的將兩個陣列進行合併,大家要搞清楚這個概念。

這個時候,問題轉化為找到陣列 A 和 B 中的第 k 大元素(kElement),那怎麼找到呢?
可以比較 A[k/2-1] 與B[k/2-1] :

  • A[k/2−1]<=B[k/2−1],則陣列A中,下標為 0 至 k/2−1 的元素均小於kElement,可以排除這部分元素;
  • A[k/2−1]>B[k/2−1],則陣列B中,下標為 0 至 k/2−1 的元素均小於kElement,可以排除這部分元素;

很容易想到,查詢範圍縮小了一半,可以在排除後的新陣列上繼續進行二分查詢,並且根據我們排除數的個數,減少 k 的值(因為我們排除的數都不大於第k 小的數)。需要注意以下幾種情況:

1.保證陣列不越界;

2.如果一個數組為空,說明該陣列中的所有元素都被排除,我們可以直接返回另一個數組中第k小的元素;

3.若 k=1,只要返回兩個陣列首元素的最小值即可。

程式碼實現

  • 時間複雜度:O(log (m+n))
  • 空間複雜度:O(1)
public class FindMedianSortedArrays_4 {

    /**
     * 常規思路:
     * 《1》合併兩個陣列在排序
     * 《2》歸併排序
     *
     * @param args
     */

    public static void main(String[] args) {
        int[] num1 = {1, 3};
        int[] num2 = {2};
        //int[] num1 = {1, 3,4,9};
        //int[] num2 = {1,2,3,4,5,6,7,8,9};
        FindMedianSortedArrays_4 findMedianSortedArrays_4 = new FindMedianSortedArrays_4();
        findMedianSortedArrays_4.findMedianSortedArrays(num1, num2);

    }

    /**
     * 二分查詢,巧妙
     * 時間複雜度:O(log (m+n))
     * 空間複雜度:O(1)
     *
     * @param nums1
     * @param nums2
     * @return
     */
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length1 = nums1.length;
        int length2 = nums2.length;
        int totalLength = length1 + length2;

        // 兩陣列總長度(totalLength)為奇數,中位數下標(midIndex)=totalLength/2,中位數=下標k所在數
        if (totalLength % 2 == 1) {
            System.out.println("兩陣列總長度(totalLength)為奇數");
            int midIndex = totalLength / 2;

            double median = getKthElement(nums1, nums2, midIndex + 1);
            System.out.println("median:" + median);
            return median;

        } else {
            // 兩陣列總長度(totalLength)為偶數,中位數下標有兩個 midIndex1,midIndex2, midIndex1=totalLength/2-1 ,midIndex2=totalLength/2,
            // 中位數=(下標midIndex1所在數+下標midIndex2所在數)/2
            System.out.println("兩陣列總長度(totalLength)為偶數");

            int midIndex1 = totalLength / 2 - 1, midIndex2 = totalLength / 2;
            double median = (getKthElement(nums1, nums2, midIndex1 + 1) + getKthElement(nums1, nums2, midIndex2 + 1)) / 2.0;
            System.out.println("median:" + median);

            return median;

        }
    }

    /**
     * 獲取第k小的元素
     *
     * @param nums1
     * @param nums2
     * @param k
     * @return
     */
    public int getKthElement(int[] nums1, int[] nums2, int k) {
        System.out.println("初始k:" + k);

        int length1 = nums1.length;
        int length2 = nums2.length;

        // 用來記錄兩個陣列尋找第k小元素的起始下標
        int index1 = 0, index2 = 0;

        while (true) {
            // 邊界情況,陣列1為空,只需要考慮陣列2
            if (index1 == length1) {
                return nums2[index2 + k - 1];
            }
            // 邊界情況,陣列2為空,只需要考慮陣列1
            if (index2 == length2) {
                return nums1[index1 + k - 1];
            }

            if (k == 1) {
                return Math.min(nums1[index1], nums2[index2]);
            }

            // 比較 num1[k/2-1] 與 num1[k/2-1]
            int compareIndex1 = Math.min(index1 + k / 2, length1) - 1;
            int compare1 = nums1[compareIndex1];
            int compareIndex2 = Math.min(index2 + k / 2, length2) - 1;
            int compare2 = nums2[compareIndex2];

            if (compare1 < compare2) {

                k -= compareIndex1 - index1 + 1;

                index1 = compareIndex1 + 1;

            } else {
                k -= compareIndex2 - index2 + 1;
                index2 = compareIndex2 + 1;

            }
            System.out.println("compare1:" + compare1);
            System.out.println("compare2:" + compare2);
            System.out.println("index1:" + index1);
            System.out.println("index2:" + index2);
            System.out.println("k:" + k);

        }

    }

}

注意:while語句中是最核心的部分,也就是二分查詢的主要思想。



好了,今天就到這裡,感謝各位看官到這裡,不如點個關注吧!

分類: 遊戲
時間: 2022-01-04

相關文章

@2022年考研學子,考研預報名正式開啟

@2022年考研學子,考研預報名正式開啟
24日,2022年考研網上預報名正式開啟.預報名時間為9月24日至27日9:00-22:00,正式報名時間為10月5日至25日同一時段.2022年考研報名有啥新變化?要注意些啥?一起關注! 研招網報流 ...

中國自動駕駛分級國標正式出臺,2022年3月1日正式實施

中國自動駕駛分級國標正式出臺,2022年3月1日正式實施
近日,市場監管總局(標準委)集中釋出了一批重要國家標準.其中,就有針對自動駕駛功能的<汽車駕駛自動化分級>國家推薦標準(GB/T 40429-2021). 據悉,該國標將於2022年3月1 ...

松下集團北京冬奧會倒計時100天活動正式開啟
2021年10月11日,松下集團在北京首鋼園開展"激情共享,從心出發"北京冬奧會倒計時100天活動,邀請奧運村部.物流部.技術部的領導上臺針對即將交付的裝置和服務,進行交付儀式,松 ...

幾何EX3 功夫牛正式開啟預售 預售價5.97萬元起

幾何EX3 功夫牛正式開啟預售 預售價5.97萬元起
[太平洋汽車網 新車頻道]9月18日,我們從官方渠道獲悉,幾何EX3 功夫牛(詢底價|查參配)正式開啟預售,預售價5.97萬元起.新車定位為小型純電動SUV,將搭載最大功率70kW的驅動電機,NEDC ...

奇瑞瑞虎7 PLUS正式開啟預售,8.69-12.39萬元

奇瑞瑞虎7 PLUS正式開啟預售,8.69-12.39萬元
日前,奇瑞瑞虎7 PLUS正式開啟預售,預售價格區間為8.69萬-12.39萬元,共提供7款車型. 外觀方面,奇瑞瑞虎7 PLUS採用晶·酷前臉設計,天使之翼星辰前格柵搭配酷黑晶格矩陣式LED大燈使得 ...

幾何EX3正式開啟預售 價格5.97萬元起

幾何EX3正式開啟預售 價格5.97萬元起
日前,幾何汽車宣佈旗下全新A0級純電動SUV--EX3 功夫牛正式開啟預售,預售價格5.97萬元起.新車搭載容量為37.23kWh的三元鋰電池組,NEDC續航里程為322km. 幾何EX3定位為A0級 ...

新車 | 預售9.59萬-12.99萬元,全新風光580正式開啟預售,1.5T動力

新車 | 預售9.59萬-12.99萬元,全新風光580正式開啟預售,1.5T動力
文:懂車帝原創 史景旭 [懂車帝原創 產品] 日前,我們從東風小康官方獲悉,旗下全新風光580正式開啟預售,新車預售價格區間為9.59萬-12.99萬元.新車對外觀進行了較大的改變,整體設計更年輕. ...

長安福特EVOS最新訊息 將9月26日正式開啟預售

長安福特EVOS最新訊息 將9月26日正式開啟預售
日前,行車視線從相關渠道獲悉,全新長安福特EVOS將在今年9月26日正式開啟預售.結合此前訊息來看,新車有望在今年第四季度內正式上市. 回顧外觀,新車造型設計年輕.時尚,且車頭上有蜂窩狀進氣格刪,內部 ...

京東公佈“雙11”節奏:10月20日晚8點正式開啟預售
36氪獲悉,京東宣佈今年"雙11"活動將於10月20日晚8點正式開啟預售.10月31日晚8點,消費者提前開搶:11月10日晚8點,京東開啟"巔峰28小時".京東 ...

上汽奧迪A7L將於9月26日正式開啟預售 車身加長/搭載3.0T發動機

上汽奧迪A7L將於9月26日正式開啟預售 車身加長/搭載3.0T發動機
[佰咖汽車·國產新車資訊]我們從相關渠道獲悉,上汽奧迪A7L 55TFSI將於9月26日正式開啟預售.新車基於奧迪的MLB EVO平臺,採用傳統的三廂設計,相對進口車型來說,車身更加進行了加長設計.後 ...

早報:iOS 15正式版釋出 廣汽豐田賽那正式開啟預定

早報:iOS 15正式版釋出 廣汽豐田賽那正式開啟預定
[手機中國早報]在9月15日蘋果秋季新品釋出會召開後,蘋果推送了備受眾人期待的iOS15 RC版本,並宣佈將於9月21日推送正式版.昨日,iOS 15正式版全面推送,新功能也如期而至.2021款廣汽豐 ...

2022年京津冀旅遊一卡通正式發行
中國經濟導報 中國發展網訊 記者荊文娜報道 近日,2022年京津冀旅遊一卡通正式發行.據瞭解,京津冀旅遊一卡通已經發行多年,是一項深受三地居民喜愛的惠民專案.實行讓利惠民政策,讓遊客充分感受京津冀綠水 ...

“點”亮世界網際網路大會|2021年“網際網路之光”博覽會開幕,“烏鎮時間”正式開啟

“點”亮世界網際網路大會|2021年“網際網路之光”博覽會開幕,“烏鎮時間”正式開啟
來源:交匯點新聞客戶端 交匯點訊 雲計算.5G技術.工業網際網路--金秋九月,水汽氤氳.白牆黛瓦的烏鎮再次迎來一場數字科技盛宴,古老的江南水鄉也再度迎來了高光時刻. 9月25日上午,2021年&quo ...

上汽奧迪A7L正式開啟預售 售價59.97-77.77萬元

上汽奧迪A7L正式開啟預售 售價59.97-77.77萬元
9月26日,上汽奧迪A7L正式開啟預售,新車共推出7款車型,全系搭載3.0TFSI V6發動機以及48V輕混系統,指導價格區間為59.97-77.77萬元.作為上汽奧迪首款車型,新車基於海外版A7打造 ...

新車 | 跨界新物種,22.78萬-26.08萬元,長安福特EVOS正式開啟預售

新車 | 跨界新物種,22.78萬-26.08萬元,長安福特EVOS正式開啟預售
文:懂車帝原創 楊藝帆 [懂車帝原創 產品] 9月26日晚,長安福特EVOS宣佈正式開啟預售,新車共推出4款車型,預售價格區間為22.78萬-26.08萬元.據悉,新車將於今年第四季度正式上市. 新車 ...

金空間裝飾正式開啟精益交付計劃

金空間裝飾正式開啟精益交付計劃
品質永遠是裝企的生命線.金空間裝飾作為25年的老品牌,品質,一直是他們考量家裝核心的唯一標準.在品質的提升上,每一年.每一個階段,金空間都在不斷突破和創新,最終實現品質交付. 品質交付,簡簡單單的四個 ...

三星正式開啟Galaxy Z Fold/Flip3旗艦摺疊屏手機12期免息支付

三星正式開啟Galaxy Z Fold/Flip3旗艦摺疊屏手機12期免息支付
筆歌科技獨家報道:三星方面訊息,其年度旗艦摺疊屏手機Galaxy Z Fold/Flip3正式向中國區消費者開啟12期免息支付,給到消費者更多的便利和多種靈活的支付方式,而且還對SAMSUNG Car ...

9月23日停機更新 長安賽年收官S25落子無悔正式開啟新賽季內容詳解

9月23日停機更新 長安賽年收官S25落子無悔正式開啟新賽季內容詳解
9月23日00:00-9月23日7:30正式服及搶先服停機更新.福利60鑽石+60銘文碎片. 一.王者峽谷 (一)打野體驗最佳化 1.野怪經濟提升 2. 野怪重新整理頻率調整 3.中路河道之靈調整 4 ...

捷尼賽思G70正式開啟預售 預售價25.58-36.18萬元 推限量版車型

捷尼賽思G70正式開啟預售 預售價25.58-36.18萬元 推限量版車型
日前,行車視線從官方渠道獲悉,全新捷尼賽思G70正式在中國市場開啟預售.新車預售價區間為25.58-36.18萬元.同時,新車還推出了G70 Edition 1限定版車型,全國限量88輛. 外觀方面, ...

Android 12 正式開啟推送!小米和OPPO等品牌首批支援機型公佈

Android 12 正式開啟推送!小米和OPPO等品牌首批支援機型公佈
2021 年 10 月 5 日,可以說是科技圈特殊的一天.首先在這一天微軟推出了最新一代的 Windows 11 正式版作業系統,內部版本號為 22000.194.戳這裡可以詳細瞭解 Windwos ...