日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode 04寻找两个正序数组的中位数(困难)二分法

發(fā)布時間:2025/3/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 04寻找两个正序数组的中位数(困难)二分法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目描述:

嘔心瀝血的一個題解,點贊關注收藏,一鍵三聯(lián),一起加入我們打卡!

題目描述:

給定兩個大小為 m 和 n 的正序(從小到大)數(shù)組 nums1 和 nums2。
請你找出這兩個正序數(shù)組的中位數(shù),并且要求算法的時間復雜度為 O(log(m + n))。
你可以假設 nums1 和 nums2 不會同時為空。

示例 1:

nums1 = [1, 3]
nums2 = [2]
則中位數(shù)是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]
則中位數(shù)是 (2 + 3)/2 = 2.5

歸并法(O(m+n))

分析之前小吐槽一句,這題自己真的沒想到O(log(m+n))的方法,只能想到O(m+n)的歸并,沒想到怎么去使用二分,后來看了題解也是才明白。但也算自己理解了和大家分享一下。

對于這個問題或許本身不難,但是可能難在O(log(m+n))的時間復雜度上。

如果真的無法想到好的方法,先想著過關,該用什么方法呢?

法一暴力法:
可以將兩個數(shù)組添加到一個總的數(shù)組中,然后給這個數(shù)組進行排序。正常的排序是**O(nlogn)**的時間復雜度。排序之后根據(jù)奇數(shù)偶數(shù)取中位數(shù)即可。

法二歸并法:
給的兩個數(shù)組本身是有序的,想必熟悉歸并排序的朋友們應該能一下就想出來這個方法,兩個有序的.只需按照以下流程即可完成歸并:

  • 待歸并的兩個數(shù)組分別設置兩個指針leftindex,rightindex均從0開始。新數(shù)組也設置游標index。

  • 比較兩數(shù)組leftindex和rightindex位置的值,較小的那個賦值到新數(shù)組中同時新數(shù)組游標和較小的那個游標均加一。

  • 重復到其中一個數(shù)組遍歷完,另一個數(shù)組剩余值直接加入后面即可。

實現(xiàn)代碼:

public double findMedianSortedArrays(int[] nums1, int[] nums2) {int a[]=new int[nums1.length+nums2.length];int lindex=0,rindex=0;int index=0;while (lindex<nums1.length&&rindex<nums2.length) {if(nums1[lindex]<nums2[rindex]){a[index++]=nums1[lindex++];}else {a[index++]=nums2[rindex++];}}while (lindex<nums1.length) {a[index++]=nums1[lindex++];}while (rindex<nums2.length) {a[index++]=nums2[rindex++];}if(a.length%2==0)return (double)(a[a.length/2-1]+a[a.length/2])/2;else {return a[a.length/2];}}

二分法(O(log(m+n)))

想到有序的,又是O(log(m+n))的時間復雜度,估計大部分人都能想到二分,我當時也是一樣,但是該怎么想呢這就是一個問題。記錄下我當初錯誤的想法:

二分,二分找到兩個中間的。然后正常有個長的,有個短的,根據(jù)兩個數(shù)值比較分類推測中位數(shù)應該在哪個區(qū)間……然后大腦就斷電了。

對于中位數(shù)的簡單分析

  • 如果兩個數(shù)組長度和為奇數(shù),那么最終這個中位數(shù)是由一位數(shù)確定的。
  • 如果兩個數(shù)組長度和為偶數(shù),那么最終這個中位數(shù)是由兩位數(shù)取平均值確定的。

對兩個數(shù)組的簡單分析

  • 兩個數(shù)組應該有一個長一點,另一個點一點(等長也不影響)。
  • 中位數(shù)可能讓兩個數(shù)組都分成兩部分:一部分小于中位數(shù),一部分大于中位數(shù)。但兩個部分合起來總數(shù)量應該一致

對兩數(shù)組和中位數(shù)位置分析

  • 我們知道兩數(shù)組雖然可能等長(不影響),但正常情況應該是一個長(m)一個短(n)。長短數(shù)組分別對應的坐標m1和n1和中位數(shù)坐標有什么關系?
  • 無論總和奇數(shù)偶數(shù),都滿足(m1+n1)=(m+n)/2;因為兩個數(shù)組都是有序的所以總共小于中位數(shù)的占一半。其中m和n是定值。也就是不管你怎么變動,這兩個坐標編號是總和為定值得

如何分析為定值得坐標

  • 既然兩個坐標的總和為定值,那么可不可以把其中一個當為自變量,一個看成自變量呢?比如x+y=5你不好分析但是y=5-x,你分析x同時y就確定了。對吧?
  • 那么選擇長的那個作為變量還是短的那個作為變量呢?短的,為啥,主要因為如果從長的當成變量咱們有些區(qū)域無法對應到短的(因為長度即使加上短的所有也到不了一半,處理起來麻煩)
  • 但是短的就可以很好避免這種情況:

所以我們就用二分去查找小的這個區(qū)間,找到最終的結果,你可能會問:什么樣情況能夠滿足確定這條線的附近就是產(chǎn)生中位數(shù)的

  • 二分進行查找編號的時候,滿足左側都比線右側小才行。這種情況在二分查找就是一個平衡的結果。

最后找到這個index線了。取值比較你還要有注意的地方

  • 取左側的時候左側如果有index為0,取右側的時候index為最大值:
  • 所以這種在你最后取值的時候,需要考慮左右側是否有值。同時取長的那個也要比較,因為可能出現(xiàn)等長情況例如:1 2 3 4,和5 6 7 8這種去到臨界。需要判斷當然在實現(xiàn)過程用三目運算簡化!

總的來說:

  • 根據(jù)短的進行二分查找位置,先找到線index,說明中位數(shù)在附近產(chǎn)生。(奇數(shù)偶數(shù)在查找因為要除2可以通用表達式)
  • 如果總個數(shù)奇數(shù),那么就是線左側最大的那個(兩個比較或只有一個)
  • 如果總個數(shù)偶數(shù),那么就是線左側最大的那個(兩個比較或只有一個)和線右側最小的那個(兩個比較或只有一個)的值取平均,注意是double類型
  • 其他注意點,搞清index從0開始,搞清邏輯上的第幾個和數(shù)組顯示使用的第幾個的index的區(qū)別

附上代碼:

public static double findMedianSortedArrays2(int[] nums1, int[] nums2) {if(nums1.length>nums2.length)//保證num1長度小,如果不小我交換一下{int team[]=nums2.clone();nums2=nums1;nums1=team;} int k=(nums1.length+nums2.length+1)/2;//理論中位數(shù)滿足的位置int left=0,right=nums1.length;//二分查找短的while (left<right) {//找到對應位置int m1=(left+right)/2;//在短的位置int m2=k-m1;//在長的第幾個//System.out.println(m1+" "+m2);if(nums1[m1]<nums2[m2-1])//left右移left=m1+1;else {//right左移right=m1;}}//System.out.println(left+" "+k);//左側最大和右側最小那個先算出來再說,根據(jù)奇偶再使用double leftbig= Math.max(left==0?Integer.MIN_VALUE:nums1[left-1], k-left==0?Integer.MIN_VALUE:nums2[k-left-1]);double rightsmall=Math.min(left==nums1.length?Integer.MAX_VALUE:nums1[left],k-left==nums2.length?Integer.MAX_VALUE:nums2[k-left]);//System.out.println(rightsmall);if((nums1.length+nums2.length)%2==0){return (leftbig+rightsmall)/2;}else {return leftbig;} }

結語

本次打卡結束,再接再勵。

至于其他方法暫時先不學了,感覺這題還是挺有難度的,需要搞明白要點時候。

最后我請你們兩連事幫忙一下:

  • 點贊、關注一下支持, 您的肯定是我在平臺創(chuàng)作的源源動力。

  • 微信搜索「bigsai」,關注我的公眾號,不僅免費送你電子書,我還會第一時間在公眾號分享知識技術。加我還可拉你進力扣打卡群一起打卡LeetCode。

  • 記得關注、咱們下次再見!

    總結

    以上是生活随笔為你收集整理的LeetCode 04寻找两个正序数组的中位数(困难)二分法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。