1. 程式人生 > >尋找兩個有序陣列的中值

尋找兩個有序陣列的中值

1. 演算法描述

有兩個陣列 A 和 B,均為有序排列,A的長度為m,B的長度為n,求 A 和 B 合在一起後的中值.

2. 問題分析

  • 這裡要注意一下:要充分利用 A和B均為有序的特性
  • 該問題進一步可轉化為求A和B的任意K值,如三分位、四分位.

思路一:將A和B合併成新的陣列

  1. /** 
  2.      * 合併有序陣列,然後尋找K值 
  3.      *  
  4.      * @param a 
  5.      *            有序陣列a 
  6.      * @param b 
  7.      *            有序陣列b 
  8.      * @param k 
  9.      *            k值位置,0<=k<=a.length+b.length-1
     
  10.      * @return k值 
  11.      */
  12.     publicstaticint findKthByMerge(int[] a, int[] b, int k) {  
  13.         System.out.println("Find kth by merge array first");  
  14.         int[] ab = newint[a.length + b.length];  
  15.         int ai = 0, bi = 0, abi = 0;  
  16.         while (ai < a.length && bi < b.length) {  
  17.             ab[abi++] = (a[ai] < b[bi]) ? a[ai++] : b[bi++];  
  18.         }  
  19.         while (ai < a.length) {  
  20.             ab[abi++] = a[ai++];  
  21.         }  
  22.         while (bi < b.length) {  
  23.             ab[abi++] = b[bi++];  
  24.         }  
  25.         System.out.println(Arrays.toString(ab));  
  26.         return ab[k];  
  27.     }  

這種方法最容易想到,合併成有序陣列後即可求任意k值,其時間複雜度為 O(m+n), 空間複雜圖為O(m+n)

這裡反思一下:真的需要合併陣列嗎?

思路二:採用掃描計數方法

  1. /** 
  2.      * 無需合併陣列,利用計數機尋找K值 
  3.      *  
  4.      * @param a 
  5.      *            有序陣列a 
  6.      * @param b 
  7.      *            有序陣列b 
  8.      * @param k 
  9.      *            k值位置,0<=k<=a.length+b.length-1,k同時充當計數器 
  10.      * @return k值 
  11.      */
  12.     publicstaticint findKthByCounter(int[] a, int[] b, int k) {  
  13.         System.out.println("Find kth by counter");  
  14.         int ai = 0, bi = 0;  
  15.         int kth = 0// 儲存K值
  16.         while (ai < a.length && bi < b.length && k >= 0) {  
  17.             kth = (a[ai] < b[bi]) ? a[ai++] : b[bi++];  
  18.             k--;  
  19.         }  
  20.         while (ai < a.length && k >= 0) {  
  21.             kth = a[ai++];  
  22.             k--;  
  23.         }  
  24.         while (bi < b.length && k >= 0) {  
  25.             kth = b[bi++];  
  26.             k--;  
  27.         }  
  28.         return kth;  
  29.     }  

本演算法是對演算法一的改進,用一個臨時變數儲存K值,而不需要講新合併的陣列單獨儲存,節省了儲存空間。

其 時間複雜度為O(m+n), 空間複雜度為O(1).

到此都是線性時間複雜度,已經是非常高效了,但又沒有更加高效的方法進一步降低時間複雜度呢?

這裡注意到原陣列有序特性,利用二分特性可以將複雜度降至對數級別。

思路三:遞迴二分

  1. /** 
  2.      * 遞迴二分查詢K值 
  3.      *  
  4.      * @param a 
  5.      *            有序陣列a 
  6.      * @param b 
  7.      *            有序陣列b 
  8.      * @param k 
  9.      *            K值位置,0<=k<=m+n-1 
  10.      * @param aStart 
  11.      *            陣列a初始查詢位置 
  12.      * @param aEnd 
  13.      *            陣列a結束查詢位置 
  14.      * @param bStart 
  15.      *            陣列b初始查詢位置 
  16.      * @param bEnd 
  17.      *            陣列b結束查詢位置 
  18.      * @return k值 
  19.      */
  20.     publicstaticint findKth(int a[], int b[], int k, int aStart, int aEnd,  
  21.             int bStart, int bEnd) {  
  22.         int aLen = aEnd - aStart + 1;  
  23.         int bLen = bEnd - bStart + 1;  
  24.         // 遞迴結束條件
  25.         if (aLen == 0) {  
  26.             return b[bStart + k];  
  27.         }  
  28.         if (bLen == 0) {  
  29.             return a[aStart + k];  
  30.         }  
  31.         if (k == 0) {  
  32.             return a[aStart] < b[bStart] ? a[aStart] : b[bStart];  
  33.         }  
  34.         // 將k按比例分配到a和b中,(k+1)=ka+kb,
  35.         int ka = (k + 1) * aLen / (aLen + bLen);  
  36.         int kb = (k + 1) - ka;  
  37.         ka += aStart;  
  38.         kb += bStart;  
  39.         // 因為a和b有序,aStart-ka , bStart-kb yi
  40. <span style="white-space:pre;">     </span>// 最大值進行比較       
  41.         if (a[ka] > b[kb]) {  
  42.             k = k - (kb - bStart); // bStart - kb 這段應當排除,調整k值
  43.             aEnd = ka; // 新k值可能存在於 aStart - ka 
  44.             bStart = kb; // 新k值可能存在於 kb - bEnd 之間
  45.         } else {  
  46.             k = k - (ka - aStart);  
  47.             bEnd = kb;  
  48.             aStart = ka;  
  49.         }  
  50.         return findKth(a, b, k, aStart, aEnd, bStart, bEnd);  
  51.     }  
本方法計算中值每次將範圍縮小一半,故而 其 時間複雜度為 lg(m+n).

3. 測試演算法

  1. 相關推薦

    Algorithm 04 : 尋找有序陣列的第N個數,要求時間複雜度為O(logm+logn)

    Question : Give a divide and conquer algorithm for the following problem : you are given two sorted lists of size m and n

    尋找有序陣列

    1. 演算法描述有兩個陣列 A 和 B,均為有序排列,A的長度為m,B的長度為n,求 A 和 B 合在一起後的中值.2. 問題分析這裡要注意一下:要充分利用 A和B均為有序的特性該問題進一步可轉化為求A和B的任意K值,如三分位、四分位.思路一:將A和B合併成新的陣列/**  

    LeetCode之4. 尋找有序陣列位數

    LeetCode之4. 尋找兩個有序陣列的中位數 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。

    leetcode演算法題4: 尋找有序陣列位數

    題目:給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會

    Leetcode(4)尋找有序陣列位數

    題目描述 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例 1: nums1 = [1, 3] nums2 = [2]

    尋找有序陣列位數-- leetCode

    尋找兩個有序陣列的中位數 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例 1: nums1 =

    尋找有序陣列位數

    題目:給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。          請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。          你

    LeetCode演算法4:java 尋找有序陣列位數

    題目描述 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例 1: nums1 = [1, 3] n

    4. 尋找有序陣列位數(python3)

     Python3: class Solution: def findMedianSortedArrays(self, nums1, nums2): """ :type nums1: List[int] :type nums2: L

    尋找有序陣列位數(LeetCode)

    想法如下: 當數的個數為奇數時,中位數就這一堆已經排好序的數最中間那一個 當數的個數為偶數時,中位數就是中間那兩個數的平均數 class Solution:     def findMedianSortedArrays(self, nums1, nums2): &nb

    Leetcode 4. Median of Two Sorted Arrays 尋找有序陣列位數

    Leetcode 4. Median of Two Sorted Arrays 尋找兩個有序陣列的中位數 標籤: Leetcode 題目地址:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 題目

    leetcode(2)尋找有序陣列位數的js實現

    一.題目描述: 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例 1: nums1 = [1, 3

    leetcode | Median of Two Sorted Arrays 尋找2有序陣列第k大的

    There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time

    【分步詳解】有序陣列位數和Top K問題

    問題介紹 這是個超級超級經典的分治演算法!!這個問題大致是說,如何在給定的兩個有序數組裡面找其中的中值,或者變形問題,如何在2個有序陣列陣列中查詢Top K的值(Top K的問題可以轉換成求第

    Java實現O(log(n+m))有序陣列第K大元素或位數

    假設有兩個從小到大的有序陣列A和B,他們的元素個數為N和M,那麼怎麼求得其第K大元素呢?同理,求其中位數就是當N+M為奇數求其第(N+M+1)/2大元素,為偶數時求(N+M)/2和(N+M+2)/2大元素的平均值。 那麼我們怎麼才能求得第K大元素呢? 分別取兩個陣列中間索

    (分治演算法)有序陣列位數和Top K問題

    問題介紹 這是個超級超級經典的分治演算法!!這個問題大致是說,如何在給定的兩個有序數組裡面找其中的中值,或者變形問題,如何在2個有序陣列陣列中查詢Top K的值(Top K的問題可以轉換成求第k個元素的問題)。這個演算法在很多實際應用中都會用到,特別是在當前大資料的

    有序陣列位數

    大小m和n分別有兩個排序陣列A和B。找到兩個排序陣列的中值。總的執行時間複雜度應該是O(log(m+n))。class Solution {  public:      /**      * @param A: An integer array.      * @param 

    資料結構演算法題/有序陣列位數

    有三種方法,時間複雜度分別是O(m+n) ,O(k),O(log(m+n)) 注意點: 判斷合併後的陣列的元素個數是奇數還是偶數 如果是奇數取中間值;如果是偶數取中間2個數的平均值。 兩種求中位數的方法: (1)方法1,判斷奇數個還是偶數個 if (lengthall % 2 == 0)

    【死磕演算法之1刷Leetcode】——找出有序陣列位數【Median of Two Sorted Arrays】O(log(m+n))

    Median of Two Sorted Arrays 題目難度:hard 題目要求: There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two s

    leetcode第四題:有序陣列位數

    給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。 請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。 你可以假設 nums1 和 nums2 不會同時為空。 示例