[程序员代码面试指南]第9章-在两个长度相等的排序数组中找到第k小的数(二分)
题目
给定两个有序数组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小的数(二分)的更多相关文章
- 《程序员代码面试指南》第二章 链表问题 在单链表和双链表中删除倒数第K个节点
题目 在单链表和双链表中删除倒数第K个节点 java代码 /** * @Description:在单链表和双链表中删除倒数第K个节点 * @Author: lizhouwei * @CreateDat ...
- 《程序员代码面试指南》第一章 栈和队列 构造数组的MaxTree
题目 给出一个无重复元素的数组,构造此数组的MaxTree, java代码 /** * @Description: 构造数组的MaxTree * @Author: lizhouwei * @Creat ...
- 《程序员代码面试指南》第一章 栈和队列 最大值减去最小值小于或等于num的数量
题目 给定整数数组arr和整数num,共返回多少的数组满足如下情况 max(arr[i...j]) - min(arr[i...j]) <= num max(arr[i...j])表示数组arr ...
- 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈
题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...
- 《程序员代码面试指南》第二章 链表问题 将单链表每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 ...
- 《程序员代码面试指南》第二章 链表问题 删除中间节点和a/b处节点
题目 例如 1-2-3-4 删除2,1-2-3-4-5 删除3 例如 a=1,b =2 java代码 /** * @Description:删除中间节点和a/b处节点 * @Author: lizho ...
- 程序员代码面试指南:IT名企算法与数据结构题目最优解
第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...
- 《程序员代码面试指南》第七章 位运算 在其他数都出现k 次的数组中找到只出现一次的数
题目 在其他数都出现k 次的数组中找到只出现一次的数 java 代码 package com.lizhouwei.chapter7; /** * @Description: 在其他数都出现k 次的数组 ...
- 程序员代码面试指南 IT名企算法与数据结构题目最优解
原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...
随机推荐
- 【NOI2015】 软件包管理器 - 树链剖分
noi2015 软件包管理器 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- Android Studio上传项目到GitHub出错
上传代码到Github出错: 一.github push文件过大(超过50M会有警告,超出100M就会被限制) error: GH001: Large files detected. this exc ...
- onlyoffice在线编辑
一.安装ONLYOFFICE Document Server 二.集成onlyoffice的二次开发 三.故障排除: 四.缺陷 五.总结 ONLYOFFICE Document Server提供文档协 ...
- 手把手教你使用VUE+SpringMVC+Spring+Mybatis+Maven构建属于你自己的电商系统之vue后台前端框架搭建——猿实战01
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是 ...
- golang 判断前缀后缀、包含关系
HasPrefix 判断字符串 s 是否以 prefix 开头:strings.HasPrefix(s, prefix string) bool HasSuffix 判断字符串 s 是否以 suffi ...
- 算法-图(1)Dijkstra求最短路径
数组dist[],是当前求到的顶点v到顶点j的最短路径长度 数组path[]存放求到的最短路径,如path[4]=2,path[2]=3,path[3]=0,则路径{0,3,2,4}就是0到4的最短路 ...
- 防止用户利用PHP代码DOS造成用光网络带宽
用PHP代码调用sockets,直接用服务器的网络攻击别的IP,常见代码如下: 代码如下:$packets = 0; $ip = $_GET[\'ip\']; $rand = $_GET[\'port ...
- SpringCloud微服务项目实战 - API网关Gateway详解实现
前面讲过zuul的网关实现,那为什么今天又要讲Spring Cloud Gateway呢?原因很简单.就是Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用 ...
- 遍历查找集合或者数组中的某个元素的值 java代码 详解 Android开发
import java.util.Scanner; public class Test21 { public static void main(String[] args) { //定义并初始化数组 ...
- EventDispatcher
事件分发类,提供事件注册.移除.触发功能 采用delegate.dictionary实现 支持自定义事件.事件采用字符串方式标识 支持 0,1,2,3,4 等5种不同参数个数的回调函数 // 路由 ...