这道题呢,给了一个非空数组一个数字k,现在需要你找出出现频率最高的K个数,其中
1、请你假设解释一定存在的,并且是唯一的
2、运行时间要求小于 O(n log n),
这道题会拆解成两部分:
1、首先将数组用哈希HashMap统计其数字频率,并转化成数组
2、利用类似于快排的方式,找到第k大的频率的开始范围
自此以后,就可以将其遍历输出。
现在题目比较新,暂时没有时间可以比较,但是AC了,从原理上说我这个寻找K不是严格的O(n),如果超时解决方法如下:
1、可以尝试使用随机快排的思想,在寻找k的时候进行一下随机化
2、使用Select算法代替,这个严格证明的是O(n)但是这个太复杂,原算法可以参考北京大学屈婉玲老师的算法分析与设计,我是最开始见于那本书上的。
Given a non-empty array of integers, return the k most frequent elements.
For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].
Note:
•You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
•Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.
public class Solution {
/** * 这道题将会先找到第K大的数(O(n)),然后遍历(O(n)) * * 寻找第K大的数,可以进行划分(有一种叫做Select的算法,将数字进行5组划分成一起,然后中位数。。那个很复杂),然后另外一种是接近于快排的,他的平均复杂度为O(n),最坏就是O(n^2)了,我先试试这种 * */
public void swap(int[] nums,int a,int b){
int tmp=nums[a];
nums[a]=nums[b];
nums[b]=tmp;
}
/** * 寻找到第K大的位置的频率,近似与快排 * */
public int findK(int[] nums,int k){
int start=0,end=nums.length-1;
while(start<=end){
int i=start,j=end;
while(i<j){
while(i<j && nums[j]>=nums[i]) j--;
swap(nums,i,j);
while(i<j && nums[i]<=nums[j]) i++;
swap(nums,i,j);
}
if(i==k-1)
return nums[i];
if(i<k-1)
start=i+1;
else end=i-1;
}
return 0;
}
public List<Integer> topKFrequent(int[] nums, int k) {
List<Integer> list = new ArrayList<Integer>();
HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(nums[i])==false) map.put(nums[i],0);
map.put(nums[i],map.get(nums[i])+1);
}
Iterator<Map.Entry<Integer,Integer>> it = map.entrySet().iterator();
int items[] =new int[map.size()];
int fre[] =new int[map.size()];
int b_fre[] =new int[map.size()];
int count=0;
while(it.hasNext()) {
Map.Entry<Integer,Integer> entry= it.next();
items[count] = entry.getKey();
fre[count] = entry.getValue();
b_fre[count++] = entry.getValue();
}
//注意这里的寻找k,因为我们是找前k个最大的,所以等同于我要找到第b_fre.length-k小的位置
int index=findK(b_fre,b_fre.length-k);
for(int i=0;i<fre.length;i++){
if(fre[i]> index)
list.add(items[i]);
}
return list;
}
}
首先说个题外话,因为感觉Leetcode编号靠后的这些解析不是很多,可能比较容易被索引到,所以可能会乱序的出一些报告,见谅
本博客可能会在我的新浪微博@MebiuW 和 个人网站同步(www.zerodigeek.com),只是可能略微延后,网站也在重建当中