[算法]最小的K个数和数据流中的中位数
1. 最小的K个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
思路
Java 中的PriorityQueue是一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。优先级队列不允许使用 null 元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。
此队列的头是按指定排序方式确定的最小元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列获取操作 poll、 remove、peek 和 element 访问处于队列头的元素。
关于PriorityQueue的更多介绍可以查看:https://blog.csdn.net/x_i_y_u_e/article/details/46381481。
关于采用PriorityQueue实现最大堆和最小堆,可以参考:http://www.cnblogs.com/yongh/p/9945539.html
https://www.cnblogs.com/Elliott-Su-Faith-change-our-life/p/7472265.html
选择最小的k个数可以用冒泡排序,复杂度为O(n*k),有点高。最经典的方法是使用最大堆,每次取数与堆顶的元素进行比较,如果堆顶元素大,则删除堆顶元素,并添加这个新数到堆中。
Java没有堆的实现,现场写也来不及,有的文献说用TreeSet,比如剑指offer,但是TreeSet是一个set,相同的数只能存一个,相比之下,Java中的PriorityQueue倒是一个不错的选择。
代码
通过PriorityQueue写法:
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
if (input == null || k <= 0 || k > input.length) {
return new ArrayList<Integer>();
}
Queue<Integer> queue = new PriorityQueue<>(k, new Comparator<Integer>() {
//降序
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i = 0; i < input.length; i++) {
if(queue.size() == k){
if(queue.peek() > input[i]){
queue.poll();
queue.add(input[i]);
}
}else{
queue.add(input[i]);
}
}
ArrayList<Integer> list = new ArrayList<>(queue);
return list;
}
}
自己实现大顶堆写法:
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> list = new ArrayList<>();
if (input == null || k <= 0 || k > input.length) {
return list;
}
int[] kArray = Arrays.copyOfRange(input,0,k);
// 创建大根堆
buildHeap(kArray); for(int i = k; i < input.length; i++) {
if(input[i] < kArray[0]) {
kArray[0] = input[i];
maxHeap(kArray, 0);
}
} for (int i = kArray.length - 1; i >= 0; i--) {
list.add(kArray[i]);
} return list;
} public void buildHeap(int[] input) {
for (int i = input.length/2 - 1; i >= 0; i--) {
maxHeap(input,i);
}
} private void maxHeap(int[] array,int i) {
int left=2*i+1;
int right=left+1;
int largest=0; if(left < array.length && array[left] > array[i])
largest=left;
else
largest=i; if(right < array.length && array[right] > array[largest])
largest = right; if(largest != i) {
int temp = array[i];
array[i] = array[largest];
array[largest] = temp;
maxHeap(array, largest);
}
} }
2. 数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路
创建优先级队列维护大顶堆和小顶堆两个堆,并且小顶堆的值都大于大顶堆的值,2个堆个数的差值小于等于1,所以当插入个数为奇数时:大顶堆个数就比小顶堆多1,中位数就是大顶堆堆头;当插入个数为偶数时,使大顶堆个数跟小顶堆个数一样,中位数就是 2个堆堆头平均数。也可使用集合类的排序方法。
代码
import java.util.Comparator;
import java.util.PriorityQueue;
public class Solution { PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
int count = 0;
public void Insert(Integer num) {
count++;
//当数据个数为奇数时,进入大根堆
if((count & 1) == 1){
minHeap.add(num);
maxHeap.add(minHeap.poll());
}else{
maxHeap.add(num);
minHeap.add(maxHeap.poll());
}
} public Double GetMedian() {
if(count == 0){
return null;
}
// 当数据个数是奇数时,中位数就是大根堆的顶点
if ((count & 1) == 1) {
return Double.valueOf(maxHeap.peek());
} else {
return Double.valueOf((minHeap.peek() + maxHeap.peek())) / 2;
}
} }
[算法]最小的K个数和数据流中的中位数的更多相关文章
- 代码题(3)— 最小的k个数、数组中的第K个最大元素、前K个高频元素
1.题目:输入n个整数,找出其中最小的K个数. 例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 快排思路(掌握): class Solution { public ...
- 编程算法 - 最小的k个数 红黑树 代码(C++)
最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出当中的最小k个数. 使用红黑树(multiset) ...
- 编程算法 - 最小的k个数 代码(C)
最小的k个数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出当中的最小k个数. 使用高速排序(Quick Sort)的方法 ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- 算法练习:寻找最小的k个数
参考July的文章:http://blog.csdn.net/v_JULY_v/article/details/6370650 寻找最小的k个数题目描述:查找最小的k个元素题目:输入n个整数,输出其中 ...
- 求一个数组中最小的K个数
方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn); 方法2:维护一个容量为K的最大堆(<算法导论>第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如 ...
- 算法笔记_035:寻找最小的k个数(Java)
目录 1 问题描述 2 解决方案 2.1 全部排序法 2.2 部分排序法 2.3 用堆代替数组法 2.4线性选择算法 1 问题描述 有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 2 ...
随机推荐
- win10下快捷命令
win10下可在win+r的输入框中: 1.gpedit.msc //本地组策略编辑器 2.regedit //注册表 3.secpol.msc //本地安全策略 4.mstsc ...
- php获取图片RGB颜色值的例子
php获取图片RGB颜色值的例子 很多图片站点都会根据用户上传的图片检索出图片的主要颜色值,然后在通过颜色搜索相关的图片. 之前按照网上的方法将图片缩放(或者马赛克)然后遍历每个像素点,然后统计处RG ...
- 为你的网站加上SSL,可以使用HTTPS进行访问
首先,我们使用的是nginx 将域名证书文件1_www.domain.com_bundle.crt .私钥文件2_www.domain.com.key保存到同一个目录,例如/usr/local/ngi ...
- webp技术探索
不管是 PC 还是移动端,图片一直是流量大头,以苹果公司 Retina 产品为代表的高 PPI 屏对图片的质量提出了更高的要求,如何保证在图片的精细度不降低的前提下缩小图片体积,成为了一个有价值且值得 ...
- GGGGCCCC
Evaluating and improving remembered sets in the HotSpot G1 garbage collector http://www.diva-portal. ...
- SQL分页参数传值 在存储过程中使用 动态SQL实现
PROCEDURE [dbo].[SP_GetList] ( ), @arrearsStatus int, , --最小ID , --每页显示记录数 ) ) AS ); declare @strSQL ...
- 每日英语:Proactive Advice for Dealing With Grief: Seek Out New Experiences
When her husband died of cancer 10 years ago, Becky Aikman says she experienced grief and adapted to ...
- Android 编程下 TextView 添加链接的一种方式
通过如下这种方式给 TextView 添加的链接支持链接样式.点击事件.href 样式,代码如下: package cn.sunzn.tlink; import android.app.Activit ...
- Vue2键盘事件
这两天学习了Vue.js 感觉组件这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记,学习一下Vue键盘事件 键盘事件 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 ...
- 多媒体文件格式之MKV
[时间:2016-07] [状态:Open] MKV是一种开源的多媒体封装格式,是Matroska中应用比较多的格式之一.常见的后缀格式是.mkv(视频,包括音频和字幕)..mka(纯音频)..mks ...