面试题40:最小的 k 个数
import java.util.Arrays;
/**
* Created by clearbug on 2018/2/26.
*
* 面试题40:最小的 k 个数
*
* 注意:因为前两天在陌陌面试时被问到的问题是最大的 k 个数,所以这里的代码也是求解最大的 k 个数的,最小的 k 个数原理是一样的。
*/
public class Solution {
public static void main(String[] args) throws InterruptedException {
Solution s = new Solution();
int[] arr = {1, 2, 3, 11, 8, 10, 5, 4, 22, 66, 23, 20};
System.out.println(Arrays.toString(s.topK1(arr, 5)));
int[] arr2 = {3, 2, 1, 11, 8, 10, 5, 4, 22, 66, 23, 20};
System.out.println(Arrays.toString(s.topK2(arr2, 5)));
}
/**
* 方法一就是利用快速排序的思想
*
* 时间复杂度:O(n)
*
* @param arr
* @param k
* @return
*/
public int[] topK1(int[] arr, int k) {
int topK = arr.length - k;
int start = 0;
int end = arr.length - 1;
int index = partition(arr, start, end);
while (index != topK) {
if (index > topK) {
end = index - 1;
index = partition(arr, start, end);
} else {
start = index + 1;
index = partition(arr, start, end);
}
}
return subArr(arr, topK, arr.length);
}
/**
* 方法二就是利用堆排序来解决了
*
* 时间复杂度:O(nlogk)
*
* @param arr
* @param k
* @return
*/
public int[] topK2(int[] arr, int k) {
int[] heap = new int[k];
int heapCount = 0;
for (int i = 0; i < arr.length; i++) {
if (heapCount < k) {
heap[heapCount++] = arr[i];
}
if (heapCount == k) { // 初始化 heap 为小顶堆
heapify(heap);
heapCount++;
continue;
}
if (heapCount > k) {
if (arr[i] > heap[0]) {
heap[0] = arr[i];
// 调整 heap 为小顶堆
adjust(heap, 0);
}
}
}
return heap;
}
private void adjust(int[] arr, int i) {
int leftChildIndex = 2 * i + 1;
int rightChildIndex = 2 * i + 2;
int smallestIndex = i;
if (leftChildIndex < arr.length && arr[leftChildIndex] < arr[smallestIndex]) {
smallestIndex = leftChildIndex;
}
if (rightChildIndex < arr.length && arr[rightChildIndex] < arr[smallestIndex]) {
smallestIndex = rightChildIndex;
}
if (smallestIndex != i) {
int temp = arr[i];
arr[i] = arr[smallestIndex];
arr[smallestIndex] = temp;
adjust(arr, smallestIndex);
}
}
private void heapify(int[] arr) {
for (int i = arr.length / 2 - 1; i >= 0; i--) {
int leftChildIndex = 2 * i + 1;
int rightChildIndex = 2 * i + 2;
int smallestIndex = i;
if (leftChildIndex < arr.length && arr[leftChildIndex] < arr[smallestIndex]) {
smallestIndex = leftChildIndex;
}
if (rightChildIndex < arr.length && arr[rightChildIndex] < arr[smallestIndex]) {
smallestIndex = rightChildIndex;
}
if (smallestIndex != i) {
int temp = arr[i];
arr[i] = arr[smallestIndex];
arr[smallestIndex] = temp;
}
}
}
private int[] subArr(int[] arr, int start, int end) {
int[] res = new int[end - start];
for (int i = start; i < end; i++) {
res[i - start] = arr[i];
}
return res;
}
private int partition(int[] arr, int start, int end) {
int privot = arr[start];
while (start < end) {
while (arr[end] >= privot && end > start) {
end--;
}
arr[start] = arr[end];
while (arr[start] <= privot && end > start) {
start++;
}
arr[end] = arr[start];
}
arr[start] = privot;
return start;
}
}
面试题40:最小的 k 个数的更多相关文章
- 剑指offer 面试题40. 最小的k个数
O(N)划分法,注意这个方法会改变原数据(函数参数是引用的情况下)!当然也可以再定义一个新容器对其划分 要求前k小的数,只要执行快排划分,每次划分都会把数据分成大小两拨.直到某一次划分的中心点正好在k ...
- leetcode 签到 面试题40. 最小的k个数
题目 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...
- 《剑指offer》面试题40. 最小的k个数
问题描述 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k ...
- 剑指 Offer 40. 最小的k个数 + 优先队列 + 堆 + 快速排序
剑指 Offer 40. 最小的k个数 Offer_40 题目描述 解法一:排序后取前k个数 /** * 题目描述:输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7. ...
- 剑指 Offer 40. 最小的k个数
剑指 Offer 40. 最小的k个数 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:ar ...
- 剑指Offer:面试题30——最小的k个数(java实现)
问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...
- 面试题30.最小的k个数
题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...
- 【Java】 剑指offer(40) 最小的k个数
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7 ...
- 40 最小的K个数(时间效率)
题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 测试用例: 功能测试(输入的数组中有相同的数字:输入的数组中 ...
- 每日一题 - 剑指 Offer 40. 最小的k个数
题目信息 时间: 2019-06-30 题目链接:Leetcode tag: 快排 难易程度:中等 题目描述: 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3. ...
随机推荐
- [JavaWeb基础] 010.Struts2 下载文件
在web开发中,我们经常会有文件的上传下载功能,上一篇的介绍中我们讲解了上传功能,那么这次我们来讲讲下载功能. 1.首先我们需要有一个用于处理下载的测试页面,也就是jsp. <body> ...
- C/C++代码优化之求两个整型的平均值
在 C/C++ 中, 直接利用 (x + y) >> 1 来计算 \(\left\lfloor {\left( {x + y} \right)/2} \right\rfloor\) (两个 ...
- Misdirection: 1靶机writeup
看下端口 nmap -A 172.16.61.131 一些坑3306无法访问,80,web2py漏洞无法利用 利用dirb遍历网站路径 得到下面命令执行漏洞 http://172.16.61.131: ...
- 初窥Ansible playbook
Ansible是一个系列文章,我会尽量以通俗易懂.诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些. Ansible系列博文直达链接:Ansible入门系列 前言 在上一篇文章中说到A ...
- Java实现 蓝桥杯 算法训练 画图(暴力)
试题 算法训练 画图 问题描述 在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色. 下图给出了一个画了两个矩 ...
- Java实现 LeetCode 576 出界的路径数(DFS || DP)
576. 出界的路径数 给定一个 m × n 的网格和一个球.球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上.下.左.右四个方向上移动使球穿过网格边界.但是,你最多可以移动 N ...
- Java实现 蓝桥杯VIP 算法训练 幂方分解
问题描述 任何一个正整数都可以用2的幂次方表示.例如: 137=27+23+20 同时约定方次用括号来表示,即ab 可表示为a(b). 由此可知,137可表示为: 2(7)+2(3)+2(0) 进一步 ...
- Java实现 LeetCode 212 单词搜索 II(二)
212. 单词搜索 II 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中&quo ...
- Java实现 LeetCode 149 直线上最多的点数
149. 直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o | ...
- Java实现 LeetCode 92 反转链表 II
92. 反转链表 II 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5-> ...