• [程序员代码面试指南]第9章-在两个长度相等的排序数组中找到第k小的数(二分)


    题目

    给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第k小的数。

    题解

    • 利用题目"在两个长度相等的排序数组中找到第上中位数"的函数
    • 分类讨论
      • k < 1 || k > lenShort + lenLong,无。
      • k <= lenShort,在两个数组前k个做二分。
      • k > lenLong,判断两个特例位置(特例部分是因为好计算可直接返回结果,并且抛去特例可满足两数组剩余待二分部份长度相等的条件),否则二分。
      • lenShort<k<lenLong,判断一个特例位置,否则二分。
    • 一些自己的理解
      • 为什么一定要找中位数?因为抛掉(小、大)两边不可能的,求剩下的中位数仍旧是原来的中位数,可以不断进行压缩(O(logn)完成。)
    • 时间复杂度O(log(min(M,N))),额外空间复杂度O(1)?可以做到,代码中是O(N)?

    代码

    public class Main {
    	public static void main(String args[]) {
    		int[] arr1 = { 1, 2, 3, 4, 5 };
    		int[] arr2 = { 3, 4, 5 };
    		int k = 8;
    		int kthNum = getKthNum(arr1, arr2, k);
    		System.out.println(kthNum);
    	}
    
    	public static int getKthNum(int arr1[], int arr2[], int k) {
    		int lenShort = Math.min(arr1.length, arr2.length);
    		int lenLong = Math.max(arr1.length, arr2.length);
    		if (arr1 == null || arr2 == null) {
    			throw new RuntimeException("Array is invaild!");
    		}
    		if (k < 1 || k > lenShort + lenLong) {
    			throw new RuntimeException("K is invaild!");
    		}
    		if (k <= lenShort) {
    			return getUpMidian(arr1, arr2, 0, k - 1, 0, k - 1);//
    		}
    		if (k > lenLong) {
    			int pos1 = k - arr2.length - 1;// arr1需要特判的位置
    			if (arr1[pos1] >= arr2[arr2.length - 1]) {//
    				return arr1[pos1];
    			}
    			int pos2 = k - arr1.length - 1;// arr2需要特判的位置
    			if (arr2[pos2] >= arr1[arr1.length - 1]) {//
    				return arr2[pos2];
    			}
    			return getUpMidian(arr1, arr2, pos1 + 1, arr1.length - 1, pos2 + 1, arr2.length - 1);
    		} else {
    			int[] arrLonger = arr1.length == lenLong ? arr1 : arr2;
    			int[] arrShorter = arr1.length == lenShort ? arr1 : arr2;
    			int pos = k - lenShort - 1;
    			if (arrLonger[pos] >= arrShorter[lenShort - 1]) {// 较长数组需要特判的位置 //
    				return arrLonger[pos];
    			}
    			return getUpMidian(arrLonger, arrShorter, pos + 1, k - 1, 0, lenShort - 1);
    		}
    	}
    
    	// 获得两个排序数组上中位数
    	public static int getUpMidian(int arr1[], int arr2[], int l1, int r1, int l2, int r2) {
    		if (arr1.length == 1) {
    			return arr1[0] < arr2[0] ? arr1[0] : arr2[0];
    		}
    		while (l1 != r1) {
    			boolean oddFlag = (r1 - l1 + 1) % 2 == 1 ? true : false;
    			int mid1 = (l1 + r1) / 2;
    			int mid2 = (l2 + r2) / 2;
    			if (arr1[mid1] == arr2[mid2]) {
    				return arr1[mid1];
    			} else if (arr1[mid1] > arr2[mid2]) {
    				r1 = mid1;
    				l2 = oddFlag ? mid2 : mid2 + 1;
    			} else {
    				r2 = mid2;
    				l1 = oddFlag ? mid1 : mid1 + 1;
    			}
    		}
    		return arr1[l1];
    	}
    }
    
    
  • 相关阅读:
    NuGet 包版本引用 | Microsoft Docs
    victoriaMetrics库之布隆过滤器
    记一次victoriaMetrics代理性能优化问题
    victoriaMetrics之byteBuffer
    面试官:什么是MySQL 事务与 MVCC 原理?
    趣说 | 数据库和缓存如何保证一致性?
    VirtualBox复制虚拟机后丢失eth0网卡的解决办法
    VirtualBox安装centos6遇到的问题
    Lambda表达式获得泛型
    springbootxjar加密打包
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/10902682.html
Copyright © 2020-2023  润新知