注:该系列博客主要用于记录学习左程云老师的算法最优解,感兴趣的同学可以看一下《程序员代码面试指南》一书
题目:
给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第k小的数。
举例:
arr1=[1,2,3,4,5],arr2=[3,4,5],k=1。
1是所有数中第1小的数,所以返回1。
arr1=[1,2,3],arr2=[3,4,5,6],k=4。
3是所有数中第4小的数,所以返回3。
要求:
如果arr1的长度是N,arr2的长度是M,时间复杂度请达到O(log(min{M,N})),额外空间复杂度为O(1)。
tip:这道题用到了题目“在两个长度相等的排序数组中找到上中位数”的算法,详细请看博主关于这一题的博客
/** * Created by Engin on 2017-03-10. * 题目:P468 * 在两个排序数组中找到第K小的数 */ public class P468 { public static int [] arr1 = {1, 2, 3, 4, 5, 6, 7, 55, 56, 57, 58, 59, 60}; public static int [] arr2 = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 50, 51, 52, 53, 54}; public static final int k = 15;// 7 15 33 public static void main(String[] args) { System.out.println(getResult(arr1, arr2, k)); } public static int getResult(int [] arr1, int [] arr2, int k){ if(arr1 == null || arr2 == null){ return -1; } if(k < 1 || k > arr1.length + arr2.length){ return -1; } int [] shortArr = arr1.length < arr2.length ? arr1 : arr2; int [] longArr = arr1.length >= arr2.length ? arr1 : arr2; int s = shortArr.length; int l = longArr.length; if(k <= s){ return getUpMedian(shortArr, 0, k-1, longArr, 0, k-1); } if(k > l){ if(shortArr[k - l - 1] >= longArr[l - 1]){ return shortArr[k - l - 1]; } if(longArr[k - s - 1] >= shortArr[s - 1]){ return longArr[k - s - 1]; } return getUpMedian(shortArr, k - l, s - 1, longArr, k - s, l - 1); } if(longArr[k - s - 1] >= shortArr[s - 1]){ return longArr[k - s - 1]; } return getUpMedian(shortArr, 0, s - 1, longArr, k - s, k - 1); } public static int getUpMedian(int [] arr1, int start1, int end1, int [] arr2, int start2, int end2){ int mid1 = 0; int mid2 = 0; int offset = 0; while(start1 < end1){ mid1 = (start1 + end1) / 2; mid2 = (start2 + end2) / 2; offset = ((end1 - start1 + 1) & 1) ^ 1; if(arr1[mid1] > arr2[mid2]){ end1 = mid1; start2 = mid2 + offset; }else if(arr1[mid1] < arr2[mid2]){ start1 = mid1 + offset; end2 = mid2; }else{ return arr1[mid1]; } } return Math.min(arr1[start1], arr2[start2]); } }