长度为N的数组arr,一定可以组成N^2个数值对
例如:arr = [3, 1, 2],
数值对有(3, 3)(3, 1)(3, 2)(1, 3)(1, 1)(1, 2)(2, 3)(2, 1)(2, 2),也就是任意两个数都有数值对,而且自己和自己也算数值对
数值对的排序规则,第一维数据从小到大,第一维数据一样的,第二维数据也从小到大
上面的数值对排序结果为:(1, 1)(1, 2)(1, 3)(2, 1)(2, 2)(2, 3)(3, 1)(3, 2)(3, 3)
给定一个数组arr,和整数k,返回第k小的数值对

what?就这么so easy的题。不就是列出所有的组合,然后比较对这些组合进行排序吗,这不是轻轻松松搞定面试官?搞定全宇宙吗?来让他们见识一下真正的技术吧。。。。

Talk is cheap. Show me the code.于是乎风骚的代码正式上线,

package com.edward.demo;import java.util.Arrays;
import java.util.Comparator;//数值对
public class Calculate {public static  class PairArr{public int first;public int second;public PairArr(int first, int second) {this.first = first;this.second = second;}}public static class PairArrCompare implements Comparator<PairArr>{@Overridepublic int compare(PairArr o1, PairArr o2) {return o1.first != o2.first ? o1.first - o2.first : o1.second - o2.second;}}public static int[] findKMinPair(int[] resources, int k){int length = resources.length;if( k > length * length){return null;}PairArr[] pairArrs = new PairArr[length * length];int index = 0;for (int i = 0; i < length; i++) {for (int j = 0; j < length; j++) {pairArrs[index ++] = new PairArr(resources[i],resources[j]);}}Arrays.sort(pairArrs,new PairArrCompare());return new int[]{pairArrs[k - 1].first,pairArrs[k-1].second};}public static void main(String[] args) {int[] resources = {1, 1, 2, 2, 2, 3,3};int k = 21;System.out.println(Arrays.toString(findKMinPair(resources,k)));}}

区区几十行代码速度解决战斗,运行的demo也很丝滑,没有一点犹豫的就执行出来了,这精简而又通俗易懂的程度,往低了说也得99吧!!!信心慢慢的提交了答卷。面试官的反应

上面代码的复杂度:面试官会给你一个O(N^2log(N^2))

方法二:

我们再来分析一下整体的数组:例如{1, 2, 3},以下是所有的情况罗列

再举个例子{1, 1, 2, 2, 2, 3, 3},罗列所有的组合:

第一个数字是1与数组{1, 1, 2, 2, 2, 3, 3}匹配,获取所有的数字对是【1,数组所有的数字】

第二个数字是1与数组{1, 1, 2, 2, 2, 3, 3}匹配,获取所有的数字对是【1,数组所有的数字】.......

所以我们可以很轻松的获取到数值对的第一位数字:arr[(K -1 )/数组的长度]

第二位数字怎么获取呢????

还是arr = {1, 1, 2, 2, 2, 3, 3}这个数组,如果去第21小的数字对,我们可以轻松的获取到第一位数字: arr[(21 -1)/ 7]  = arr[2] = 2 ,第一位是2

所有的数值对是从小大排列,arr有3个数字2,那么就会有 {2,2,2} 分别于{1, 1, 2, 2, 2, 3, 3}组成的组合,那么第二位的数字我们就呼之欲出了,arr[  (21 - 小于2数字的个数 * 7  - 1)  / 3] = arr [( 21 - 2 * 7 - 1) /3]=arr[2] = 2;最后的结果就是 {arr[2],arr[2]} ={2,2}

show me the code

public static int[] findKMinPair2(int[] resources, int k){int length = resources.length;if( k > length * length){return null;}Arrays.sort(resources);//找出第一位数字int firstNum = resources[(k - 1)/ length];//小于firstNum的个数int lessFirstNumSize = 0;//找出等于firstNum的个数int firstNumSize = 0;for (int i = 0; i < length && resources[i] <= firstNum; i++) {if(resources[i] < firstNum){lessFirstNumSize++;}else {firstNumSize++;}}int restK = k - (lessFirstNumSize * length);return new int[]{firstNum,resources[(restK - 1) / firstNumSize]};}

搞定,骚年你是不是感觉导致已经结束了???no  no  no, 骚年 too  young  too  simple,你还是不太了解面试官

方法二天然的需要排序,如果是无需呢?这个问题就换成了,在一个无序的数组中获取到第K小的数据,是不是有点熟悉,这就是TOP-K问题,,大名鼎鼎的BFPTR算法(也叫中位数的中位数算法),该算法可以从一堆无序数字中拿出第k小的数字,而且,而且最神奇的是!!!该算法在最坏情况下的时间复杂度竟然只有O(N)

public static int[] findKMinPair2(int[] resources, int k){int length = resources.length;if( k > length * length){return null;}//找出第一位数字int firstNum = bfptr(resources,0,length - 1,(k -1 )/ length + 1);//小于firstNum的个数int lessFirstNumSize = 0;//找出等于firstNum的个数int firstNumSize = 0;for (int i = 0; i < length && resources[i] <= firstNum; i++) {if(resources[i] < firstNum){lessFirstNumSize++;}else {firstNumSize++;}}int restK = k - (lessFirstNumSize * length);int second = bfptr(resources,0,length - 1,(restK - 1) / firstNumSize + 1);return new int[]{firstNum,second};}public static void main(String[] args) {int[] resources = {1, 1, 2, 2, 2, 3, 3};int k = 21;System.out.println(Arrays.toString(findKMinPair2(resources,k)));}public static int findMid(int[] arr,int l,int r){if (l == r) return arr[l];int i;int n = 0;for(i = l; i < r - 5; i += 5){insertSort(arr, i, i + 4);n = i - l;swap(arr,l + n / 5, i + 2);}//处理剩余元素int num = r - i + 1;if(num > 0){insertSort(arr, i, i + num - 1);n = i - l;swap(arr,l + n / 5, i + num / 2);}n /= 5;if(n == l) return arr[l];return findMid(arr, l, l + n);}public static int findMidIndex(int[] arr,int l,int r,int num){for (int i = l; i <= r; i++) {if (arr[i] == num) return i;}return -1;}public static int Partition(int[] arr, int l, int r, int p){swap(arr,p, l);int i = l;int j = r;int pivot = arr[l];while(i < j){while(arr[j] >= pivot && i < j)j--;arr[i] = arr[j];while(arr[i] <= pivot && i < j)i++;arr[j] = arr[i];}arr[i] = pivot;return i;}//插入排序public static void insertSort(int[] arr,int l,int r){for (int i = l + 1; i <= r; i++) {if (arr[i - 1] > arr[i]) {int t = arr[i];int j = i;while (j > l && arr[j - 1] > t) {arr[j] = arr[j - 1];j--;}arr[j] = t;}}}//数组元素交换public static void swap(int[] arr,int i,int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static int bfptr(int[] arr,int l,int r,int k){int num = findMid(arr, l, r);    //寻找中位数的中位数int p =  findMidIndex(arr, l, r, num); //找到中位数的中位数对应的indexint i = Partition(arr, l, r, p);int m = i - l + 1;if(m == k) return arr[i];if(m > k)  return bfptr(arr, l, i - 1, k);return bfptr(arr, i + 1, r, k - m);}

骚年 想知道更多的套路吗?欢迎关注:叮铛的公众号,套路三联。。。。。。

回复  8888可以领取面试资料

阿里面试算法题(一)相关推荐

  1. 【LintCode 题解】阿里面试算法题:两个链表的交叉

    题目描述 请写一个程序,找到两个单链表最开始的交叉节点. 如果两个链表没有交叉,返回null. 在返回结果后,两个链表仍须保持原有的结构. 可假定整个链表结构中没有循环. 样例 1: 输入:A: a1 ...

  2. 常见的面试算法题:创建几个线程按顺序打印数字或者字母(多线程编程)(套用该模板即可)

    常见的面试算法题:创建几个线程按顺序打印数字或者字母(多线程编程)(套用该模板即可) 比较典型的题目,如下有: 题目一: 1.启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程 ...

  3. 常考面试算法题类型总结(来自知乎)

    作者:牛客网 链接:https://www.zhihu.com/question/24964987/answer/200681301 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  4. Java常见的面试算法题:实现两个线程交替打印1到100的数

    Java常见的面试算法题:实现两个线程交替打印1到100的数 思路: 这是涉及到多个线程打印的问题,一定会用到锁的(synchronized),故这就是一个多线程打印的典型案例. 代码实现: pack ...

  5. 力扣高频算法php_互联网公司最常见的面试算法题有哪些?

    很多时候,你即使提前复习了这些最常见的面试算法题,你依旧无法通过算法面试! 为什么?你在提前准备复习的时候,在网上找了半天相应题目的分析文章,但你看了就是不懂. 你在面试的时候,卡壳了,一时间忘了怎么 ...

  6. 【笔试面试题】腾讯2013实习生面试算法题及参考答案

    总结了一下自己遇到的以及同学遇到的面试算法题,是技术二面. 有几道题给出了参考答案,还有几道没有好的思路.路过的大侠如果有好的思路请留个言交流下呗~ 1.八数码问题:3*3的格子,有1~8个数,空了一 ...

  7. 互联网公司最常见的面试算法题大集合!

      转载于 新智元   来源:Github 编辑:元子 [导读]LeetCode是一个美国的在线编程网站,收集了各个大厂的笔试面试题,对找工作的毕业生和开发者来说,非常有价值.很多求职者都会在Leet ...

  8. 一道小面试算法题的思路

    一道小算法题的思路 有这么一道小面试算法题:给定一个长度为 n 的整数数组,下标为 i 的元素表示第 i 天某个股票的价格,每次最多持有一股,每次买卖最多一股,在最多只买卖一次的情况下(先买后卖,不考 ...

  9. C++经典面试算法题

    #include <assert.h> #include <string.h> #include <stack>// // C++ 经典面试算法题 [7/28/20 ...

  10. 阿里、华为、美团,大厂面试算法题,这些你会吗?

    名师 带你刷爆LeetCode 算法知识 讲解+训练 免费0元报名参加 在讲到 AI 算法工程师时,大部分同学关注点都在高大上的模型,一线优秀的项目.但大家往往忽略了一点,人工智能的模型.项目最终还是 ...

最新文章

  1. 快速让你明白Objective-C的语法(和Java、C++对比)
  2. linux介绍及目录结构(一)
  3. 信息系统项目管理师-论文专题(一)论文写作框架+10大管理关系
  4. boost::log::keywords::format用法的测试程序
  5. matlab调用c语言驱动函数,[转载]Matlab调用C语言函数
  6. 具有InlfuxDB的Spring Boot和Micrometer第1部分:基础项目
  7. php node 目录,node.js基于fs模块对系统文件及目录进行读写操作的方法详解
  8. Dubbo + RestEasy 实现文件上传与下载
  9. 边缘计算计算机科学与技术,边缘计算现状与展望-ComputerScience-WayneStateUniversity.PDF...
  10. 未能连接驱动人生服务器怎么解决,重装系统后无法上网?驱动人生提供3个解决方案...
  11. linux下载m3u8工具,m3u8命令行下载工具
  12. 计算机硬件系统的五大组成部分是什么,硬件系统的五大组成部分
  13. 【STM32学习笔记】(6)—— 跑马灯实验详解
  14. 2019前端面试常问
  15. 13651.Python数字读作中文大写
  16. 微软蓝牙鼠标卡顿问题解决
  17. 离职后竟半夜偷溜回办公室写代码?为自由软件而战斗的程序员
  18. 目标检测训练数据扩充增强工具使用说明
  19. 怎么用python画指北针?
  20. 钉钉小程序图表刷新 antv-f2

热门文章

  1. LoadRunner压力测试:测试报告结果分析
  2. 零基础 Java 学习笔记
  3. 达梦数据库可视化管理工具的配置
  4. C专家编程 三 C语言声明是如何形成的
  5. 监狱电视系统设计原则及应用场景
  6. 手机12306买卧铺下铺技巧_手机12306怎么买下铺
  7. jQuery周日历选择器代码
  8. 假设检验-统计学自学笔记
  9. 广州计算机公办学校有哪些,广州各区小学对口中学列表,小学对口哪些初中?这里有名单大全...
  10. 信息系统安全等级保护三级的基本要求 引用的规范文件