在两个排序数组中找到第k小的数

来源:互联网 发布:数据恢复哪个好用 编辑:程序博客网 时间:2024/05/17 02:59

注:该系列博客主要用于记录学习左程云老师的算法最优解,感兴趣的同学可以看一下《程序员代码面试指南》一书

题目:

给定两个有序数组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]);    }}


                                             
0 0
原创粉丝点击