求一个数组中最小的K个数
方法1:先对数组进行排序,然后遍历前K个数,此时时间复杂度为O(nlgn);
方法2:维护一个容量为K的最大堆(《算法导论》第6章),然后从第K+1个元素开始遍历,和堆中的最大元素比较,如果大于最大元素则忽略,如果小于最大元素则将次元素送入堆中,并将堆的最大元素删除,调整堆的结构;
方法3:使用快速排序的原理,选择出数组中第K大的元素,select(a[], k, low, high)
- 选取数组中a[high]为基准,将数组分割为A1和A2,A1中的元素都比a[high]小,A[2]中的元素都比a[high]大,将a[high]放到合适的位置;
- 如果k小于a[high]实际位置的index,则递归调用此函数select(a[], k, low, index - 1);
- 如果k大于a[high]实际位置的index,则递归调用此函数selet(a[], k, index + 1, high);
- 如果k等于a[hign]实际位置的index,则此时的index位置之前的数即为数组中最小的k个数;
- /**
- * Created by Administrator on 2014/12/8.
- * 输入N个整数,输出最小的K个
- */
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Scanner;
- public class MinKArray {
- /* 用二叉树表示一个堆 */
- private class Heap {
- private Node root;
- private class Node {
- int key;
- Node left;
- Node right;
- Node(int key) {
- this.key = key;
- }
- }
- /* 建立最大堆,将元素插入到堆的合适位置 */
- public void put(int key) {
- root = put(root, key);
- }
- private Node put(Node x, int key) {
- if (x == null)
- return new Node(key);
- int cmp = key - x.key;
- if (cmp > 0) {
- int tmp = x.key;
- x.key = key;
- key = tmp;
- x.right = put(x.right, key);
- } else if (cmp < 0) {
- x.left = put(x.left, key);
- }
- return x;
- }
- public void deleteMax() {
- root = deleteMax(root);
- }
- private Node deleteMax(Node x) {
- if (x == null)
- return null;
- if ((x.left == null) && (x.right != null)) {
- int tmp = x.key;
- x.right.key = x.key;
- x.key = tmp;
- x.right = deleteMax(x.right);
- } else if ((x.right == null) && (x.left != null)) {
- int tmp = x.key;
- x.left.key = x.key;
- x.key = tmp;
- x.left = deleteMax(x.left);
- } else if ((x.left == null) && (x.right == null)) {
- x = null;
- } else {
- int cmp = x.left.key - x.right.key;
- if (cmp >= 0) {
- int tmp = x.key;
- x.key = x.left.key;
- x.left.key = tmp;
- x.left = deleteMax(x.left);
- } else {
- int tmp = x.key;
- x.key = x.right.key;
- x.right.key = tmp;
- x.right = deleteMax(x.right);
- }
- }
- return x;
- }
- public void printHeap(Node x) {
- if (x == null)
- return;
- System.out.print(x.key + " ");
- printHeap(x.left);
- printHeap(x.right);
- }
- }
- /* 使用一般的排序算法,然后顺序输出前K个元素 */
- public int[] minKArray1(int[] a, int k) {
- Arrays.sort(a);
- for (int i = 0; i < k; i++) {
- System.out.print(a[i] + " ");
- }
- return Arrays.copyOfRange(a, 0, k);
- }
- /* 求出数组中第K大的元素,然后顺序遍历所有元素 */
- public int[] minKArray2(int[] a, int k) {
- minKArray2(a, k, 0, a.length - 1);
- return a;
- }
- /* 利用快速排序的原理,以a[high]为基准,将a[high]放到相应的位置
- * 左边的都比它小,右边的都比它大 */
- private void minKArray2(int[] a, int k, int low, int high) {
- if (low <= high) {
- int l = low, r = high - 1;
- int x = a[high];
- for (int i = low; i < high; i++) {
- if (l <= r) {
- if (a[l] > x) {
- int tmp = a[r];
- a[r] = a[l];
- a[l] = tmp;
- r--;
- }
- if (a[l] <= x) {
- l++;
- }
- }
- }
- int tmp = a[l];
- a[l] = a[high];
- a[high] = tmp;
- if (l < k) {
- minKArray2(a, k, l + 1, high);
- } else if (l > k) {
- minKArray2(a, k, low, l - 1);
- } else {
- for (int i = 0; i < k; i++) {
- System.out.print(a[i] + " ");
- }
- }
- }
- }
- /* 维护一个容量为K的最大堆,《算法导论》第6章堆排序 */
- public int[] minKArray3(int[] a, int k) {
- Heap h = new Heap();
- for (int i = 0; i < k; i++) {
- h.put(a[i]);
- }
- for (int i = k; i < a.length; i++) {
- if (a[i] >= h.root.key) {
- continue;
- } else {
- h.put(a[i]);
- h.deleteMax();
- }
- }
- h.printHeap(h.root);
- return a;
- }
- public static void main(String[] args) {
- Scanner scan = new Scanner(System.in);
- ArrayList<Integer> array = new ArrayList<Integer>();
- while (scan.hasNext()) {
- array.add(scan.nextInt());
- }
- int[] a = new int[array.size()];
- for (int i = 0; i < a.length; i++) {
- a[i] = array.get(i);
- }
- MinKArray mka = new MinKArray();
- mka.minKArray1(a, 8);
- System.out.println();
- mka.minKArray2(a, 8);
- System.out.println();
- mka.minKArray3(a, 8);
- System.out.println();
- }
- }
求一个数组中最小的K个数的更多相关文章
- 【算法】数组与矩阵问题——找到无序数组中最小的k个数
/** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...
- [算法]找到无序数组中最小的K个数
题目: 给定一个无序的整型数组arr,找到其中最小的k个数. 方法一: 将数组排序,排序后的数组的前k个数就是最小的k个数. 时间复杂度:O(nlogn) 方法二: 时间复杂度:O(nlogk) 维护 ...
- 小米笔试题:无序数组中最小的k个数
题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...
- 求给定数据中最小的K个数
public class MinHeap { /* * * Top K个问题,求给定数据中最小的K个数 * * 最小堆解决:堆顶元素为堆中最大元素 * * * */ private int MAX_D ...
- 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数
题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...
- 求数组中最小的k个数
题目:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. package test; import java.util.Arra ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
- [剑指offer]数组中最小的K个数,C++实现
原创博文,转载请注明出处! http://github.com/wanglei5205 http://cnblogs.com/wanglei5205 # 题目 输入n个整数,找出其中最小的K个数.例如 ...
- 找到数组中最小的k个数
/*输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字, 则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...
随机推荐
- 用Visual C#向access添加数据
(1)创建并打开一个OleDbConnection对象. (2)创建一个插入一条记录的SQL语句. (3)创建一个OleDbCommand对象. (4)通过此OleDbCommand对象完成对插入一条 ...
- NSInternalInconsistencyException: loaded the "XXXView" nib but the view outlet was not set
运行过程中App崩溃,报错如标题. 原因: viewController的view没有绑定xib的view. 解决方法: 在File's Owner中将view与viewController的view ...
- 128. Longest Consecutive Sequence *HARD* -- 寻找无序数组中最长连续序列的长度
Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...
- iOS应用架构现状分析
iOS从2007年诞生至今已有近10年的历史,10年的时间对iOS技术圈来说足够产生相当可观的沉淀,尤其这几年的技术分享氛围无论国内国外都显得异常活跃.本文就iOS架构这一主题,结合开发圈里讨论较多的 ...
- js——<script>标签的加载顺序
用了很久的JavaScript,今天突然就碰见了将一个js文件放在<head></head>与<body></body>标签中,一个不可以执行,一个可以 ...
- String.equals()方法的实现代码,
通常对String的比较有两种情况,一个是使用==,另一个是使用equals()方法,注意==是对对象的地址进行比较的,而String中的equals()方法是覆盖了Object类的方法,并且实现为对 ...
- c#获取系统时间的方法(转)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ...
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- RewriteRule参数
RewriteCond指令格式 [说明]定义重写发生的条件 [语法]RewriteCond TestString CondPattern [flags] RewriteCond指令定义一条规则条件.在 ...
- hihocode ---1032
#include<iostream> #include<cstring> #include<cstdio> using namespace std; + ; ]; ...