給定兩個有序數組arr1和arr2,已知兩個數組的長度分別爲 m1 和 m2,求兩個數組中的第 K 小數。要求時間複雜度O(log(m1 + m2))。數組
例如 arr1 = [1, 2,3],arr2 = [3,4,5,6],K = 4。函數
則第 K 小數爲 3.測試
例如 arr1 = [0,1,2],arr2 = [3,4,5,7,8], K = 3;code
則第 K 小數爲 2.blog
難排序
這道題和我上次講的那一道題是很是很是相似的:遞歸打卡1:在兩個長度相等的排序數組中找到上中位數,若是沒看過的建議先看下,只是今天的這道題比上次的那道題少難一點,原理同樣。遞歸
下面我隨便講一下原理吧:採用遞歸的方法不斷縮小 K 的,把求第 K 小元素轉化爲第 (K-K/2) 小元素....我舉個例子吧,比較容易理解。token
咱們假定 arr1 = [1, 2,3],arr2 = [3,4,5,6],K = 4。get
和上一道題相似(注意:這裏咱們假設K從0算起,也就是有第0小元素,至關於令 K = K - 1),令原理
mid1 = K/2 = 1。
mid2 = K/2 = 1。
此時 arr2[mid2] > arr2[mid1],那麼問題轉化爲在數組 arr1[mid1+1...m1]和數組 arr2[0...m2] 尋找第(K-md1-1)小的元素。
不過這裏須要注意的是,有可能 k/2 的值是大於 m1 或者 m2的,因此若是 k/2 > m1 或者 m2 的話,咱們直接令 md1 = m1-1 或者 md2 = m2-1 就好了。
代碼以下:
// 因爲中位數會受長度是奇偶數的影響,因此咱們能夠把問題轉化爲求 // ((n+m+1)/2+(n+m+2)/2)/2。 public double findMedianSortedArrays(int[] nums1, int[] nums2) { int n = nums1.length; int m = nums2.length; // return (findKthNumber(nums1, 0, n-1, nums2,0,m-1,(n+m+1)/2) + // findKthNumber(nums1, 0, m-1,nums2,0,m-1,(n+m+2)/2)) /2; return 1; } public static int findKth(int[] arr1, int[] arr2, int k) { if(arr1 == null || arr1.length < 1) return arr2[k-1]; if(arr2 == null || arr2.length < 1) return arr1[k-1]; // 注意這個函數的參數有7個,上面那個函數的參數只有3個,同名不一樣函數哈 return findKth(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, k - 1); } public static int findKth(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2, int k) { // 遞歸結束條件 if(l1 > r1) return arr2[l2 + k]; if(l2 > r2) return arr1[l1 + k]; if (k == 0)// 注意,k == 0的結束條件與上面兩個結束條件不能顛倒。 return Math.min(arr1[l1],arr2[l2]); int md1 = l1 + k/2 < r1 ? l1 + k/2 : r1; int md2 = l2 + k/2 < (r2 - l1) ? l2 + k/2 : r2; if(arr1[md1] < arr2[md2]) return findKth(arr1, md1 + 1, r1, arr2, l2, r2, k - k / 2 - 1); else if (arr1[md1] > arr2[md2]) return findKth(arr1, l1, r1, arr2, md2 + 1, r2, k - k / 2 - 1); else return arr1[md1];//返回arr2[md2]也能夠,同樣的。 } // 測試 public static void main(String[] args) { int[] arr1 = {1, 2, 3}; int[] arr2 = {0,4, 5, 6, 7, 8}; System.out.println(findKth(arr1, arr2, 2)); }
能夠用迭代嗎?固然能夠,不過留給你本身。
下次我還會再出一道與這兩道相似的題,不過,難度遞增。總共有三道這種題,必定要本身手動寫代碼,必定要本身手動寫代碼,必定要本身手動寫代碼。