LeetCode 4

題目

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
    

思路

  • 先說我的解題思路(太久沒做題了拥峦,思路很怪)钟鸵。我寫了一個O(2*logm*logn)的算法舆吮。主要的思路是:

    • 假設:第一個數(shù)組為A,長度為m乖坠;第二個數(shù)組為B薄榛,長度為n;AB合并排序好的數(shù)組為C(并沒有排序勒极,只是為了方便說明),長度為m+n虑鼎。
      1. 二分數(shù)組A辱匿,查找小于等于C[(m+n)/2+1]的最大的數(shù)所在的位置,二分中點的index為indexDim炫彩。
      1. 那么如何比較二分中點的數(shù)和C[(m+n)/2+1]的大小呢匾七,因為A,B均有序,所以看index就行了媒楼。就對于這個A[indexDim]乐尊,在B中二分查找小于等于A[indexDim]中最大的數(shù)所在的位置L戚丸。
      1. 然后我只需要比較L + indexDim + 1(m+n)/2 + 1即可划址。
      1. 交換A扔嵌、B再來一次。
  • 這個思想的問題在于代碼寫起來很麻煩夺颤,需要考慮奇數(shù)偶數(shù)的情況痢缎,特別是偶數(shù)時,還需要特殊處理(m+n)/2這個位置的數(shù)字世澜。所以我也交了幾次才AC了独旷。并且時間復雜度上也沒有O(log(m+n))的算法優(yōu)。

  • 因為最近剛開始學習JAVA寥裂,所以代碼質量比較低嵌洼。

    // 二分第二個數(shù)組
    public int binarySearchTwo(int[] arr, int target, int flag) {
        int l = 0, r = arr.length - 1;
        if (l == r) {
          return arr[l] > target ? -1 : 0;
        }
        while (l < r) {
          int dim = (l + r) / 2 + 1;
          if ((arr[dim] < target && flag == 0) || (arr[dim] <= target && flag == 1)) {
            l = dim;
          } else {
            r = dim - 1;
          }
        }
        return (arr[l] < target && flag == 0) || (arr[l] <= target && flag == 1) ? l : -1;
    }
    
    // 二分第一個數(shù)組
    public int binarySearchOne(int[] nums1, int[] nums2, int flag) {
        int l = 0, r = nums1.length - 1, m = nums1.length + nums2.length;
        while (l < r) {
          int dim = (l + r) / 2 + 1;
          int b = this.binarySearchTwo(nums2, nums1[dim], flag) + 1;
          if (dim + b <= m / 2) {
            l = dim;
          } else {
            r = dim - 1;
          }
        }
        return l;
    }
    
    /**
    * 尋找自己前一個的數(shù)
    * @param indexOne
    * @param indexTwo
    * @return
    */
    public int maxNext(int[] num1, int[] num2, int indexOne, int indexTwo) {
        int resOne = indexOne == 0 ? -10000 : num1[indexOne - 1];
        int resTwo = indexTwo == -1 ? -10000 : num2[indexTwo];
        return Math.max(resOne, resTwo);
    }
    
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length == 0) {
          return nums2.length % 2 == 0 ? (nums2[nums2.length / 2 - 1] + nums2[nums2.length / 2]) / 2.0 : (nums2[nums2.length / 2]);
        } else if (nums2.length == 0) {
          return nums1.length % 2 == 0 ? (nums1[nums1.length / 2 - 1] + nums1[nums1.length / 2]) / 2.0 : (nums1[nums1.length / 2]);
        }
        
        int m = nums1.length + nums2.length;
        int indexOne = binarySearchOne(nums1, nums2, 0);
        int bOne = binarySearchTwo(nums2, nums1[indexOne], 0);
        int firstOne = maxNext(nums1, nums2, indexOne, bOne);
        int indexOneSum = indexOne + bOne + 2;
        int indexTwo = binarySearchOne(nums2, nums1, 1);
        int bTwo = binarySearchTwo(nums1, nums2[indexTwo], 1);
        int firstTwo = maxNext(nums2, nums1, indexTwo, bTwo);
        
        if (m % 2 == 0) {
          return indexOneSum == m / 2 + 1 ? (nums1[indexOne] + firstOne) / 2.0 : (nums2[indexTwo] + firstTwo) / 2.0;
        } else {
          return indexOneSum == m / 2 + 1 ? nums1[indexOne] : nums2[indexTwo];
        }
    }
    
  • 做完以后去看了一下別人的思路就是很常規(guī)的尋找第k小的問題:

    • 當A[mid] < B[mid]時,第k小出現(xiàn)在(A_Right + B_Left)中封恰。
    • 當A[mid] >= B[mid]時麻养,第k小出現(xiàn)在(A_Left + B_Right)中 。
    • 并且通過(m+n+1)/2(m+n+2)/2的小技巧統(tǒng)一解決了奇數(shù)诺舔、偶數(shù)的問題鳖昌。
    • 在LeetCode上兩種方法跑下來時間是差不多的~
      public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length, n = B.length;
        int l = (m + n + 1) / 2;
        int r = (m + n + 2) / 2;
        return (getKMin(A, 0, B, 0, l) + getKMin(A, 0, B, 0, r)) / 2.0;
      }
    
      public double getKMin(int[] A, int Astart, int[] B, int Bstart, int k) {
        if (Astart > A.length - 1) return B[Bstart + k - 1];
        if (Bstart > B.length - 1) return A[Astart + k - 1];
        if (k == 1) return Math.min(A[Astart], B[Bstart]);
        
        int Amin = Integer.MAX_VALUE, Bmin = Integer.MAX_VALUE;
        if (Astart + k / 2 - 1 < A.length) Amin = A[Astart + k / 2 - 1];
        if (Bstart + k / 2 - 1 < B.length) Bmin = B[Bstart + k / 2 - 1];
        
        return Amin < Bmin
          ? getKMin(A, Astart + k / 2, B, Bstart, k - k / 2)
          : getKMin(A, Astart, B, Bstart + k / 2, k - k / 2);
      }
    
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市低飒,隨后出現(xiàn)的幾起案子许昨,更是在濱河造成了極大的恐慌,老刑警劉巖褥赊,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糕档,死亡現(xiàn)場離奇詭異,居然都是意外死亡拌喉,警方通過查閱死者的電腦和手機翼岁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來司光,“玉大人琅坡,你說我怎么就攤上這事〔屑遥” “怎么了榆俺?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坞淮。 經(jīng)常有香客問我茴晋,道長,這世上最難降的妖魔是什么回窘? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任诺擅,我火速辦了婚禮,結果婚禮上啡直,老公的妹妹穿的比我還像新娘烁涌。我一直安慰自己苍碟,他們只是感情好,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布撮执。 她就那樣靜靜地躺著微峰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抒钱。 梳的紋絲不亂的頭發(fā)上蜓肆,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天,我揣著相機與錄音谋币,去河邊找鬼仗扬。 笑死,一個胖子當著我的面吹牛蕾额,可吹牛的內(nèi)容都是我干的厉颤。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼凡简,長吁一口氣:“原來是場噩夢啊……” “哼逼友!你這毒婦竟也來了?” 一聲冷哼從身側響起秤涩,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤帜乞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后筐眷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體黎烈,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年匀谣,在試婚紗的時候發(fā)現(xiàn)自己被綠了照棋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡武翎,死狀恐怖烈炭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宝恶,我是刑警寧澤符隙,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站垫毙,受9級特大地震影響霹疫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜综芥,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一丽蝎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膀藐,春花似錦屠阻、人聲如沸红省。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽类腮。三九已至臊泰,卻和暖如春蛉加,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缸逃。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工针饥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人需频。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓丁眼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親昭殉。 傳聞我的和親對象是個殘疾皇子苞七,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,750評論 0 33
  • 晚上看完書準備睡覺挪丢,辰寶投進懷抱蹂风,嚷嚷著讓講故事,說實話講故事我實在不擅長乾蓬,突然想到今天帶他出去氣死人的狀態(tài)惠啄,隨口...
    虛空中的兔子閱讀 458評論 0 2
  • 我懺悔: 我對父親的不尊重 我對父親口出惡言 我對父母的憎恨 我對老公的憎恨 我對老公的背叛 我對老公的報復 我對...
    竺子閱讀 187評論 1 0
  • 這周的作業(yè)越來越難了 好幾次畫到沮喪 疊色經(jīng)常疊成黑漆漆臟兮兮的………… but畫完之后覺得還可以啦 兩個周以前的...
    Nikikki閱讀 360評論 2 4
  • 【git操作指令】 git help # 顯示command的help git show # 顯示某次提交的內(nèi)容...
    liudai123閱讀 208評論 0 0