题目

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

题解

  • 利用题目"在两个长度相等的排序数组中找到第上中位数"的函数
  • 分类讨论
    • k < 1 || k > lenShort + lenLong,无。
    • k <= lenShort,在两个数组前k个做二分。
    • k > lenLong,判断两个特例位置(特例部分是因为好计算可直接返回结果,并且抛去特例可满足两数组剩余待二分部份长度相等的条件),否则二分。
    • lenShort<k<lenLong,判断一个特例位置,否则二分。
  • 一些自己的理解
    • 为什么一定要找中位数?因为抛掉(小、大)两边不可能的,求剩下的中位数仍旧是原来的中位数,可以不断进行压缩(O(logn)完成。)
    • 为什么一定要两个数组长度相等?这样才能利用对称的性质不断取mid比不断删两端不可能的部分?(todo进一步思考)
  • 时间复杂度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];
}
}

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

  1. 《程序员代码面试指南》第二章 链表问题 在单链表和双链表中删除倒数第K个节点

    题目 在单链表和双链表中删除倒数第K个节点 java代码 /** * @Description:在单链表和双链表中删除倒数第K个节点 * @Author: lizhouwei * @CreateDat ...

  2. 《程序员代码面试指南》第一章 栈和队列 构造数组的MaxTree

    题目 给出一个无重复元素的数组,构造此数组的MaxTree, java代码 /** * @Description: 构造数组的MaxTree * @Author: lizhouwei * @Creat ...

  3. 《程序员代码面试指南》第一章 栈和队列 最大值减去最小值小于或等于num的数量

    题目 给定整数数组arr和整数num,共返回多少的数组满足如下情况 max(arr[i...j]) - min(arr[i...j]) <= num max(arr[i...j])表示数组arr ...

  4. 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈

    题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...

  5. 《程序员代码面试指南》第二章 链表问题 将单链表每K个节点之间逆序

    样例 链表1-2-3-4-5-6-7-8-9-10 K=3 ,结果 3-2-1-6-5-4-9-8-7-10 java代码 /** * @Description:将单链表每K个节点之间逆序 * @Au ...

  6. 《程序员代码面试指南》第二章 链表问题 删除中间节点和a/b处节点

    题目 例如 1-2-3-4 删除2,1-2-3-4-5 删除3 例如 a=1,b =2 java代码 /** * @Description:删除中间节点和a/b处节点 * @Author: lizho ...

  7. 程序员代码面试指南:IT名企算法与数据结构题目最优解

      第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...

  8. 《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数

    题目 在其他数都出现k 次的数组中找到只出现一次的数 java 代码 package com.lizhouwei.chapter7; /** * @Description: 在其他数都出现k 次的数组 ...

  9. 程序员代码面试指南 IT名企算法与数据结构题目最优解

    原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...

随机推荐

  1. 使用halo搭建自己的博客并配置https域名访问

    首先进行java配置 # 1. 下载jdk [下载地址](https://www.oracle.com/cn/java/technologies/javase-downloads.html) - 一定 ...

  2. 树莓派 4B VNC Viewer 显示 cannot currently show the desktop 的解决方法 (图文)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/ZChen1996/article/de ...

  3. 双向BFS和启发式搜索的应用

    题目链接 P5507 机关 题意简述   有12个旋钮,每个旋钮开始时处于状态 \(1\) ~ \(4\) ,每次操作可以往规定方向转动一个旋钮 (\(1\Rightarrow2\Rightarrow ...

  4. linux驱动之内核空间几种长延时的实现策略的优劣评估

    本文转载自http://blog.chinaunix.net/uid-23769728-id-3084737.html 这里所谓的长延时,是指其实现时间延时的粒度可以在HZ这一水准上.<深入Li ...

  5. J20航模遥控器开源项目系列教程(三)开发说明 | 想要自己改造程序,扩充功能,怎么实现?

    我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/C ...

  6. selenium定位方法(一)

    selenium定位方法-(一) 1.定位页面元素的方式(By类的方法) 1)id定位:通过页面元素的id属性值来定位一个页面元素       注意事项:如果每次刷新网页之后元素的id属性值都不同,说 ...

  7. 第5篇 Scrum冲刺博客

    1.站立式会议 1.1 会议图片 1.2 项目进展 成员 昨日任务 今日计划完成任务 陈忠明 歌曲信息的上传/下载包 歌曲批量下载压缩包 吴茂平 完善评论系统 新消息提醒功能设计 黄海钊 修改代码规范 ...

  8. python 递归删除空文件夹

    Python如何递归删除空文件夹 1.Python如何递归删除空文件夹,这个问题很常见.但大多数人的解决办法都是自己实现递归函数解决这个问题,其实根本不用那么麻烦.Python中的os.walk提供了 ...

  9. Python语言中的关键字(自己做的读书笔记)

    电脑配置:联想笔记本电脑 windows8系统 Python版本:2.7.8 本文章撰写时间:2015.1.1 作者:陈东陈 阅读说明: 1.本文都是先解释,后放图片: 2.文中斜体部分要么为需要输入 ...

  10. C# Mongo DB 修改多层嵌套集合中的字段

    C# Mongo DB 修改嵌套集合中的字段 虽然c#的mongo 驱动很强大,而且还支持linq,但是一些复杂的操作语句还是比较困难 这里我用Bson实现功能 这是模型(我这里有多层嵌套) publ ...