您的位置:首页 > Web前端

剑指Offer:最小的K个数Java/Python

2019-05-03 12:59 246 查看

1.题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

2.算法描述

这种类型的题目都可以用排序算法做,只是时间效率有差别。
最推荐的是堆排序,或者说,一旦出现了最大/最小的k个,首先想到的是堆。\red{一旦出现了最大/最小的k个,首先想到的是堆。}一旦出现了最大/最小的k个,首先想到的是堆。堆其实是基于完全二叉树实现的。
堆分最大堆和最小堆。堆也称为优先队列(PriorityQueue)
最大堆:堆中值最大的元素将最先出堆。
最小堆:堆中值最小的元素将最先出堆。
这里用语言自带的堆 和 自己手写堆排序两种方法。

3.代码描述

3.1.Java代码

/*
方法1:基于自带的优先队列,java中的优先队列是基于堆实现的。所有元素进入一个最小堆,然后从最小堆中弹出k个元素就是k个最小的元素。
*/
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> ans = new ArrayList<>();
if(input==null || k<=0 || k > input.length)
return ans;
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int e: input){
pq.offer(e);
}
for(int i=0;i<k;i++){
int e = pq.poll();
ans.add(e);
}
return ans;
}
}
/*
方法1:基于自带的优先队列,java中的优先队列是基于堆实现的。只用一个容量为k个最大堆,因为是找最小的k个元素,所以当堆满的时候,判断当前元素和是否小于堆根元素,如果小于,就弹出这个最大元素,将当前元素进入最大堆。遍历完成之后,堆中的k个元素就是最小的k个元素。
*/
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> ans = new ArrayList<>();
if(input==null || k<=0 || k > input.length)
return ans;
//默认是最小堆,这里是最大堆 并且容量为k
PriorityQueue<Integer> pq = new PriorityQueue<>(k,(o1,o2)->o2-o1);
for(int n: input){
if(pq.size()<k){
pq.offer(n);
}
else if(pq.peek()>n){
pq.poll();
pq.offer(n);
}
}
while(!pq.isEmpty()){
ans.add(pq.poll());
}
return ans;
}
}
/*
手写堆排序,然后返回排序后数组的前k个元素
*/
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> ans = new ArrayList<>();
if(input==null || k<=0 || k>input.length)
return ans;
heapSort(input);
for(int i=0;i<k;i++)
ans.add(input[i]);
return ans;
}
private void heapSort(int[] arr){
int len = arr.length;
for(int i=len/2-1; i>=0; i--)//建立最大堆  从倒数第二层开始过滤 形成一个最大堆
percDown(arr, i, len);
for(int i=len-1;i>0;i--){//堆顶是最大的元素,将其与最后元素交换,然后将新的堆顶元素过滤
int t = arr[i];
arr[i] = arr[0];
arr[0] = t;
percDown(arr, 0, i);
}
}
private void percDown(int[] arr, int p, int n){//将指向的元素向下过滤
int parent, child;
int x = arr[p];
for(parent=p; parent*2+1<n;parent=child){
child = parent*2+1;
if(child!=n-1 && arr[child]<arr[child+1])
child++;
if(x>=arr[child])
break;
else
arr[parent] = arr[child];
}
arr[parent] = x;
}
}

3.2.Python代码

#手写堆排序
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
# write code here
ans = []
if not tinput or k<=0 or k>len(tinput):
return  ans
self.heapSort(tinput)
return tinput[:k]
def heapSort(self, arr):
def percDown(arr, p, n):
x = arr[p]
parent = p
while parent*2+1<n:
child = parent*2+1
if child!=n-1 and arr[child]<arr[child+1]:
child += 1
if x>=arr[child]:
break
else:
arr[parent] = arr[child]
parent = child
arr[parent] = x
l = len(arr)
for i in range(l//2-1, -1, -1):
percDown(arr, i, l)
for i in range(l-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
percDown(arr, 0, i)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: