题目

给定两个有序数组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. MySQL设置跳过密码验证

    1.linux系统下 在/etc/my.cnf文件中, [mysqld]下面新增skip-grant-tables,然后重启服务器.

  2. Salesforce学习笔记之Actions and Recommendations

    设置Actions and Recommendations(Salesforce提供的标准元素),Salesforce上的文档说有两种方法,即Deployment和Process Builder(通过 ...

  3. 自建本地服务器,自建Web服务器——保姆级教程!

    搭建本地服务器,Web服务器--保姆级教程! 本文首发于https://blog.chens.life/How-to-build-your-own-server.html. 先上图!大致思路就是如此. ...

  4. 微信小程序之蓝牙广播信息

    期初第一次做蓝牙开锁的时候遇到的最尖锐的问题就是ios设备如何对获取的广播信息进行读取,大概用了4中方式,都无法解决,最后不得不求助官方人员.给了一个方法,大家可以参考.在此附图: 由于mac地址是6 ...

  5. 感谢 Vue.js 拯救我这个前端渣渣,让 PowerJob 有了管理后台界面

    本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri HelloGitHub 推出的<讲解开源项目>系列. 对于大部分非前端程序员来说,写网页无疑是一件非常痛 ...

  6. 直播报名 | 8.29 Kylin Meetup – 来聊聊云原生

    云原生的巨浪正在席卷全球的软件产业,包括开源和商业软件.Apache Kylin 正在为此而积极准备着:基于新的计算和存储引擎,即将发布的 Kylin 4.0 将实现真正的计算和存储分离,减小运维难度 ...

  7. 第1章 Spark SQL概述

    第1章 Spark SQL概述 1.1 什么是Spark SQL Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作 ...

  8. 【Spring】Spring如何实现多数据源读写分离?这是我看过最详细的一篇!!

    写在前面 很多小伙伴私聊我说:最近他们公司的业务涉及到多个数据源的问题,问我Spring如何实现多数据源的问题.回答这个问题之前,首先需要弄懂什么是多数据源:多数据源就是在同一个项目中,会连接两个甚至 ...

  9. 仿京东BOE官网图片链接

  10. 用 Python 写个七夕表白神器

    今天是七夕节,相比于现代人自创的 502,不对是 520,七夕才是中国传统意义上的情人节,本文分享几个 Python 表白程序,情侣可以现学现用,单身的话也可以先收藏一下,说不定下次就用上了. 爱心树 ...