剑指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)
相关文章推荐
- 剑指Offer:把数组排成最小的数Java/Python
- 剑指Offer:面试题30——最小的k个数(java实现)
- 剑指Offer:面试题33——把数组排成最小的数(java实现)(未完待续)
- 剑指Offer:面试题8——旋转数组的最小值(java实现)
- 剑指Offer:链表中环的入口结点Java/Python
- 剑指offer 面试题8 旋转数组的最小值 java版答案
- 剑指Offer:滑动窗口的最大值Java/Python
- c++/java/python priority_que实现最大堆和最小堆
- 剑指offer第一题和第二题(python版和java版)
- 剑指Offer:两个链表的第一个公共结点Java/Python
- 剑指Offer:数组中重复的数字Java/Python
- 剑指Offer:机器人的运动范围Java/Python
- 剑指Offer面试题33:把数组排成最小的数 Java 实现,三种方法
- JAVA实现旋转数组的最小数字问题(《剑指offer》)
- 最小的K个数 java实现 剑指offer
- 剑指offer面试题11:旋转数组的最小数字(Java 实现)
- 旋转数组的最小数字-剑指Offer(Java语言)
- 剑指Offer:孩子们的游戏(圆圈中最后剩下的数)Java/Python
- 剑指Offer:求1+2+3+...+n Java/Python
- 剑指Offer面试题33(java版):把数组排成最小的数