Solution 5: Top K

问题描述

输入一个整形数组和K,输出数组中前K大的元素们。

解决思路

思路1:排序

如果用快排,平均时间复杂度为O(nlogn),最坏时间复杂度为O(n^2);空间复杂度为O(logn)~O(n);

如果用堆排,时间复杂度为O(nlogn),空间复杂度为O(1).

注意:

Java中Arrays.sort()方法默认实现为归并排序,时间O(nlogn),空间O(n)。

思路2:借用快排的partition函数

较思路1的改进在于,不一定要完全将整个数组进行排序,快排中的partition函数能够保证partition后的元素位置之前的元素均大于等于(或小于等于)该指向元素。

平均时间复杂度为O(n),最坏时间复杂度和快排的一样O(n^2)。

思路3:大数据下的堆排

如果场景为数据量很大,或者甚至是无穷量的数据时,此时可借用堆排的思想。

具体做法为,如果是输出前K大,那么需要维护一个大小为K的最小堆,之后的元素与堆顶元素进行比较,如果更大则进入堆中,再调整堆。

时间复杂度为O(n*logk + k),空间复杂度为O(k)。

程序

public class TopK {
	// sort
	public List<Integer> getTopKBySort(int[] nums, int k) {
		List<Integer> res = new ArrayList<Integer>();
		if (nums == null || nums.length == 0 || nums.length < k || k <= 0) {
			return res;
		}

		Arrays.sort(nums);
		for (int i = 0; i < k; i++) {
			res.add(nums[i]);
		}
		return res;
	}

	// partition
	public List<Integer> getTopKByPartition(int[] nums, int k) {
		List<Integer> res = new ArrayList<Integer>();
		if (nums == null || nums.length == 0 || nums.length < k || k <= 0) {
			return res;
		}

		int part = partition(nums, 0, nums.length - 1);
		while (true) {
			if (part == k - 1) {
				for (int i = 0; i < k; i++) {
					res.add(nums[i]);
				}
				break;
			} else if (part < k - 1) {
				part = partition(nums, part + 1, nums.length - 1);
			} else {
				part = partition(nums, 0, part - 1);
			}
		}

		return res;
	}

	private int partition(int[] nums, int begin, int end) {
		int low = begin - 1, high = end;
		int pivot = nums[end];

		while (true) {
			while (low < high && nums[++low] >= pivot) {
				;
			}
			while (low < high && nums[--high] <= pivot) {
				;
			}
			if (low >= high) {
				break;
			}
			swap(nums, low, high);
		}
		swap(nums, low, end);
		return low;
	}

	private void swap(int[] nums, int low, int high) {
		int tmp = nums[low];
		nums[low] = nums[high];
		nums[high] = tmp;
	}

	// heap
	public int[] getTopKByHeap(int[] nums, int k) {
		if (nums == null || nums.length == 0 || nums.length < k || k <= 0) {
			return null;
		}

		int[] res = new int[k];
		for (int i = 0; i < nums.length; i++) {
			if (i < k) {
				res[i] = nums[i];
			} else if (i == k) {
				buildMinHeap(res);
			} else {
				if (nums[i] > res[0]) {
					res[0] = nums[i];
					fixMaxDown(res, 0);
				}
			}
		}

		return res;
	}

	private void fixMaxDown(int[] heap, int i) {
		int tmp = heap[i];
		int j = 2*i +1;

		while (j < heap.length) {
			while (j+1 < heap.length && heap[j+1] < heap[j]) {
				++j;
			}
			if (tmp<heap[j]) {
				break;
			}
			heap[i] = heap[j];
			i = j;
			j = 2*i + 1;
		}

		heap[i] = tmp;
	}

	private void buildMinHeap(int[] heap) {
		for (int i = heap.length/2 - 1; i >= 0; i--) {
			fixMaxDown(heap, i);
		}
	}
}
时间: 2024-11-10 04:26:08

Solution 5: Top K的相关文章

347. Top K Frequent Elements

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: 347. Top K Frequent ElementsYou may assume k is always valid, 1 ≤ k ≤ number of unique elements. Your algorithm's

Top K Frequent Words

Given a list of words and an integer k, return the top k frequent words in the list. Given [ "yes", "lint", "code", "yes", "code", "baby", "you", "baby", "chrome", &

Top k Largest Numbers

Given an integer array, find the top k largest numbers in it. Example Given [3,10,1000,-99,4,100] and k = 3.Return [1000, 100, 10]. 思路:由于需要按从大到小的顺序,因此直接用PriorityQueue即可,用Partition的方法的话还需要排序.直接用PriorityQueue 写的代码量少. 1 class Solution { 2 /* 3 * @param

LeetCode OJ 347. Top K Frequent Elements hashmap+排序求解

题目链接:https://leetcode.com/problems/top-k-frequent-elements/. 347. Top K Frequent Elements My Submissions QuestionEditorial Solution Total Accepted: 15510 Total Submissions: 36453 Difficulty: Medium Given a non-empty array of integers, return the k mo

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

Top k 问题

Top K的问题: 给出大量数据,找出其中前K个最大(小)的数,或者在海量数据中找到出现频率最好的前K个数. 一.给出大量数据(N个),找出其中前K个最大数(没有其他资源上的限制) 1.使用排序算法 直接使用排序算法,如快速排序,然后遍历找到最大的K个数.时间复杂度为O(NlogN): 2.部分排序 因为,只要求出前K个最大值,所以我们不必全部排好.思路是:随意选出K个数形成一个数组,然后按从大到小进行排序,再从剩下的数中,选取一个数和数组中的最小值进行比较,若小于最小值,则取下一个数继续比较:

Spark 编程实战之经典算法TOP K

Top K Top K算法有两步,一是统计词频,二是找出词频最高的前K个词. 1.实例描述 假设取Top 1,则有如下输入和输出. 输入: Hello World Bye World Hello Hadoop Bye Hadoop Bye Hadoop Hello Hadoop 输出: 词Hadoop 词频4 2.设计思路 首先统计WordCount的词频,将数据转化为(词,词频)的数据对,第二个阶段采用分 治的思想,求出RDD每个分区的Top K,最后将每个分区的Top K结果合并以产生新的集

Top K问题!!!!!!!!!!!!!

转:http://blog.csdn.net/boo12355/article/details/11788655 Top K 算法详解应用场景: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.        假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询它的用户越多,也就是越热门.),请你统计最热门的10个查询串,要求使用的内存不能超过1G. 必备知识:什么

Top k问题的讨论(三种方法的java实现及适用范围)

在很多的笔试和面试中,喜欢考察Top K.下面从自身的经验给出三种实现方式及实用范围. 合并法 这种方法适用于几个数组有序的情况,来求Top k.时间复杂度为O(k*m).(m:为数组的个数).具体实现如下: /** * 已知几个递减有序的m个数组,求这几个数据前k大的数 *适合采用Merge的方法,时间复杂度(O(k*m); */ import java.util.List; import java.util.Arrays; import java.util.ArrayList; public