找到n中最小的k个数
题目:n个数中,求最小的前k个数。
这道题在各个地方都看到过,在国内出现的频率也非常高。
面完阿里回来听说这道题又被考了,所以还是决定回来写一写,对于这种高频题。。。顺便再吐槽一下阿里的面试,我竟然一道题都不用做,只是纯粹地过简历。。。导致我都不知道我究竟错在哪里。
解法:
1. brute force。 O(k*n)复杂度;
2. sort。O(k+n*lgn)复杂度;
3. 最大堆。每次替代的是大小为k的最大堆的最大值。O(k+(n-k)lgk)复杂度。
int findKthByHeap(int arr[], int n, int k) {
make_heap(arr, arr + k);
for (int i = k; i < n; ++i) {
if (arr[i] < arr[]) {
pop_heap(arr, arr + k); // pop_heap()用于弹出堆中的第一个元素,并把它放到区间的最后一个位置,然后重新将前面的元素构建成一个堆。
arr[k - ] = arr[i]; //替换最后一个数
push_heap(arr, arr + k); //pop_heap()用于将指定区间的最后一个元素加入堆中并使整个区间成为一个新的堆。注意前提是最后一个元素除外的所有元素已经构成一个堆。
}
}
return arr[];
}
4. 最小堆。和sort类似,只是建堆后只求前k次。O(n+k*lgn)复杂度。在网上看到一个优化,就是pop出第k小的数(堆顶)的时候,最多只需要调整k-1层(不需要调到堆底)。所以可以优化到O(n+k^2)。当然这个建堆需要O(n)的空间复杂度,所以还是弱一点。
int findKthByHeap(int arr[], int n, int k) {
make_heap(arr, arr + n, greater<int>());
for (int i = ; i < k - ; ++i) {
pop_heap(arr, arr + n, greater<int>());
n--;
}
return arr[];
}
5. 类quick sort。求第k小的数。pivot用的是“五分化中项的中项”。因为每次划分之后,只需要考虑其中一部分的数,证明过程类似于堆排序建堆用了O(n)的开销证明。开销也在O(n)。
关于partition,要用的是双向划分, 避免的是所有数字都相等的情况。
双向划分也有两种方式,最后一种最为简洁,关键在于arr[l]这个元素因为先保存下来了,所以替换它是安全的,所以我们是先找arr[r],然后将它保存到arr[l];然后再找arr[l],将它保存到arr[r]。循环退出时,arr[l]已经保存到arr[r]的位置了,所以循环不变式是arr[l]仍然可以安全地被替代。
int partition2(int arr[], int n) {
int l = ;
for (int i = ; i < n; ++i) {
if (arr[i] < arr[]) {
swap(arr[++l], arr[i]);
}
}
swap(arr[], arr[l]);
return l;
}
int partition(int arr[], int n) {
int l = , r = n;
while (true) {
while (++l < n && arr[l] < arr[]);
while (arr[--r] > arr[]);
if (l >= r) break;
swap(arr[l], arr[r]);
}
swap(arr[], arr[r]);
return r;
}
int partition3(int arr[], int n) {
int l = , r = n - ;
int p = arr[];
while (l < r) {
while (r > l && arr[r] >= p) r--;
arr[l] = arr[r];
while (r > l && arr[l] <= p) l++;
arr[r] = arr[l];
}
arr[l] = p;
return l;
}
int quickSelect(int arr[], int n, int k) {
int p = partition3(arr, n);
if (p == k - ) return arr[p];
else if (p < k - ) {
return quickSelect(arr + p + , n - p - , k - p - );
} else {
return quickSelect(arr, p, k);
}
}
“五分化中项的中项”划分法:
- 将输入数组的N个元素划分为[n/5]组,最后一个组剩下的n mod5组成;
- 寻找每一组的中位数:首先对每组的元素进行插入排序,排序后选出一些中位数;这样可以确保,对于这一些中位数,大于它们的数的个数约等于小于它们的数的个数;
- 对找出的[n/5]个中位数,继续递归找到其中位数,作为最终的pivot;
- 基于pivot进行partition划分;

找到n中最小的k个数的更多相关文章
- 找到数组中最小的k个数
/*输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, 则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数
题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...
- 小米笔试题:无序数组中最小的k个数
题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...
- 求一个数组中最小的K个数
方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...
- 求给定数据中最小的K个数
public class MinHeap { /* * * Top K个问题,求给定数据中最小的K个数 * * 最小堆解决:堆顶元素为堆中最大元素 * * * */ private int MAX_D ...
- Java找N个数中最小的K个数,PriorityQueue和Arrays.sort()两种实现方法
最近看到了 java.util.PriorityQueue.刚看到还没什么感觉,今天突然发现他可以用来找N个数中最小的K个数. 假设有如下 10 个整数. 5 2 0 1 4 8 6 9 7 3 怎么 ...
- [剑指offer]数组中最小的K个数,C++实现
原创博文,转载请注明出处! http://github.com/wanglei5205 http://cnblogs.com/wanglei5205 # 题目 输入n个整数,找出其中最小的K个数.例如 ...
随机推荐
- 【JAVA、C++】LeetCode 007 Reverse Integer
Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 解题思路:将数字 ...
- Price List
Price List Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/131072 K (Java/Others)Tota ...
- codeforces 489C.Given Length and Sum of Digits... 解题报告
题目链接:http://codeforces.com/problemset/problem/489/C 题目意思:给出 m 和 s,需要构造最大和最小的数.满足长度都为 m,每一位的数字之和等于 s. ...
- 引水入城(codevs 1066)
题目描述 Description 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政 区划十分特殊,刚好构成一个N行M列的矩形,如上图所示,其中每个格子都代表一座城 市,每座 ...
- Linux命令--文件权限和磁盘管理
1.chmod chmod [ugoa][+-=][rwx] file 改变目录或者文件的权限. u是user,g是group,o是other,a是all. +是添加权限,-是去掉权限,=改变权限为. ...
- java equals 和 "==" 比较
java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(== ...
- Maven使用笔记(四)pom.xml配置详解
pom.xml文件配置详解 --声明规范 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...
- jQuery Mobile 基础(第四章)
1.主题 jQuery Mobile 提供了5种不同的主题样式, 从 "a" 到 "e" - 每一种主题的按钮,工具条,内容块等等颜色都不一致,每个主题的视觉效 ...
- C# WPF 之 遍历子控件
/// <summary> /// 检查非空字段 /// </summary> /// <param name="IsOk"></para ...
- LCS(打印全路径) POJ 2264 Advanced Fruits
题目传送门 题意:两个字符串结合起来,公共的字符只输出一次 分析:LCS,记录每个字符的路径 代码: /* LCS(记录路径)模板题: 用递归打印路径:) */ #include <cstdio ...