Algorithm学习笔记 --- 寻找 K 大数
来源:互联网 发布:移动硬盘mac无法拷贝 编辑:程序博客网 时间:2024/05/17 01:57
Q:
给你一个无序的序列,要你找出第K大的数是什么?
Answer:
Answer 1:
利用Hash,桶排序等方式,是第一个想到的(编程珠玑中所记)
假设数列中最大数为max,最小数为min,那么首先做一个数组长度为max – min + 1,
然后做散列函数为an – min,对于冲突的处理是计数,最后从后往前扫描一次整个新建的数组,
即可得到第k大的数。这样看似可以在O(n)的复杂度内解决问题,是一个经典的空间换时间的办法,
但是具体情况是,其实这个算法的时间复杂度是 O( n * ( max – min ) )的,所以这个的时间复杂度
完全取决于数组的最大与最小数的差。但是一般在实际的数据中,数列是很分散的,如果特别分散的话,
完全有可能max – min 是远大于n的,那么这个效果就非常差了,
代码如下:O( n * ( max – min ) )
//Find K-th Number#include <iostream>#include <stdio.h>using namespace std;int find_k(int p[], int n, int k){int KList[k];for(int i = 0; i < k; i++)kList[i] = 0;for(int i = 0; i < n; i++){for(int j = 0; j < k; j++){if(p[i] > kList[j]){for(int I = K - 1; I > j; I--){kList[I] = kList[I - 1]kList[j] = p[i]break;}}}}return kList[k - 1]}int main(){//....//return 0}
Answer2:
编程之美的解法:使用部分快排的方法
方法是从最开始的原始方法开始讨论展开的。得到k个最大数,首先做排序,然后取前k个即可,
而用快排或者堆排序,这样的时间复杂度是o(N*logN),于是基于这样的时间复杂度为起点,开始逐步的优化。
优化的原因是,要得到k个最大数,只需要前k个数有序,时间复杂度的优化,只能从去除对k个以后的数进行排序展开。
优化方法如下:首先随机在数列中找到一个数,作为轴值,将数列划分成Sa和Sb两个部分,其中Sa中存放大于或等于轴值的数,Sb存放小于轴值
的数,划分完成后,有如下两种情况:
1.Sa元素小于等于k,那么k个最大数为Sa中所有数,以及Sb中最大的k-|Sa|个数
2.Sa元素大于等于k,那么需要找到Sa中最大的k个数
代码如下:o(N*logN)
int find_k(vector find, int k){if(find.size() < k){return 0;}int p = find.at(0);vector findA, findB;for(int i = 1; i < find.size(); i++){if(find.at(i) >= p)findA.push_back(find.at(i))elsefindB.push_back(find.at(i))}if(findA.size() == (k - 1)){return p;}else if(findA.size(0 > (k - 1)){return find_k(findA, k);}else{return find_k(findB, k findA.size());}}
Answer3:用 小顶堆优化
其实这是没有意义的事情,毕竟我要的只是第k个数,所以我只要知道我那k个数组中,
最小的那个数即可,也就是一直保存的k个数,可以是无序的,但是,一定要知道其中最小值,
有一个最小值,并且整体不一定有序,这样的数据结构一下就想到了最小值堆,首先将堆的接口声明如下
代码如下:
O(N * logK)
classminHeap{ private: int*Heap;//用于存放堆元素的数组 intsize;//数组大小 intn;//堆中元素个数 voidshiftdown(int);//堆的下拉操作 public: minHeap(int*Heap,intnum,intmax) boolisLeaf(intpos)const intleftchild(intpos)const intrightchild(intpos)const intparent(intpos)const boolinsert(constint); boolremoveMin(int&); intgetMin(); };
- Algorithm学习笔记 --- 寻找 K 大数
- 寻找前K大数
- 寻找第k大数
- Algorithm学习笔记 --- 大数阶乘算法模板
- 寻找第K大数的方法
- 编程之美--寻找K大数
- 寻找第K大数方法总结
- 寻找无序数组中的第K大数
- 寻找无序数组中的第K大数
- 寻找K大数的各种方法
- 寻找第k大数(快排思想)
- 寻找前K大数(复习各种排序)
- POJ3579 Median 寻找第K大数
- SzNOI c016 : 寻找第K大数
- 寻找无序数组中的第K大数
- 寻找数组中第K大数
- 分治算法--寻找第k大数
- 寻找第K大数的方法
- 写clone()方法时,通常都有一行代码
- JVM7、8详解及优化
- Oracle常用字典表
- Android软键盘(六)如何监听到软件盘显示与隐藏的事件
- 面向对象的特征
- Algorithm学习笔记 --- 寻找 K 大数
- 深入理解Spark RDD抽象模型
- 自动生成数据库表设计(一)之获取JDBC获取元数据
- 微信小程序
- 什么是内部类?Static Nested Class 和 Inner Class的不同
- PHP阿里云短信API发送代码
- 系统设计与架构
- 【HTML5】Canvas_变色
- 四个月的蜕变之自己对面向对象思想的理解