`

使用堆求数组第K大的数

 
阅读更多

在上一篇博文中,O(n)复杂度,求数组中第2大的数 ,ansjsun同学留下一个非常有价值的回复:

ansjsun 写道
大概看了下代码...
这么排啊...其实答案应该是堆排...

第二大是 O(2*logn) = O(n)

 

感谢ansjsun提供的思路,下面是我实现的代码 

 

import java.util.Arrays;


public class MaxHeap {
	private int[] array;
	private int size;
	public MaxHeap(int[] array){
		this.array = Arrays.copyOf(array, array.length);
		this.size = this.array.length;
	}
	//求第K大的数值
	public int kmax(int k){
		if(k<1 || k>size){
			throw new IllegalArgumentException("k must be between 1 and " + size);
		}
		this.buildMaxHeap();
		for(int count=1,i=size-1;i>=1;i--,count++){
			if(k == count){
				break;
			}
			swap(0,i);
			maxHeapify(0,i);
		}
		return array[0];
	}
	
	//建立最大堆
	public void buildMaxHeap(){
		for(int i=parent(size-1);i>=0;i--){
			maxHeapify(i,size);
		}
	}
	
	//排序
	public void sort(){
		this.buildMaxHeap();
		for(int i=size-1;i>=1;i--){
			swap(i,0);
			maxHeapify(0,i);
		}
	}
	//使i节点比左节点和右节点都要大。
	//@param i 节点下标
	//@param size 堆的元素个数
	private void maxHeapify(int i, int size){
		int maxIndex = i;
		int left = left(i);
		int right = right(i);
		if(left<size && array[left]>array[maxIndex]){
			maxIndex = left;
		}
		if(right<size && array[right]>array[maxIndex]){
			maxIndex = right;
		}
		if(maxIndex != i){
			swap(i,maxIndex);
			//子节点发生了变化,需要重新计算最大值
			maxHeapify(maxIndex,size);
		}
	}
	
	private void swap(int i,int j){
		int tmp  = array[i];
		array[i] = array[j];
		array[j] = tmp;
	}
	
	private int left(int i){
		return (i<<1) + 1;
	}
	
	private int right(int i){
		return (i<<1) + 2;
	}
	private int parent(int i){
		return (i-1)>>1;
	}
	
	public void print(){
		int i=0;
		for(int width=1;;width*=2){
			for(int count=0;count<width;count++){
				System.out.print(array[i]+ " ");
				i++;
				if(i==size){
					System.out.println();
					return;
				}
			}
			System.out.println();
		}
	}
	
	public static void main(String[] args){
		int[] a = new int[]{1,2,3,4,5};
		MaxHeap heap = new MaxHeap(a);
		//第二大的数
		System.out.println(heap.kmax(2));
	}
}

 

分享到:
评论

相关推荐

    计算整形数组中第k小的数

    2. **部分排序**:如果只需要找到第k小的数,并不关心整个数组的完全排序,可以使用堆排序或快速选择算法,仅对前k个元素进行排序,大大减少不必要的比较和交换次数。 3. **利用已知条件**:如果数组本身已经部分...

    求第K大元素

    在编程和算法设计中,"求第K大元素"是一个常见的问题,特别是在数据处理和排序算法的场景下。这个问题的基本目标是从一个数组或集合中找出第K个最大的元素,其中K通常是一个正整数,且K小于等于数组的元素个数。这个...

    java-leetcode题解之第215题数组中的第K个最大元素.zip

    当遍历完整个数组后,堆顶的元素就是我们要找的第K大元素。这种解决方案的时间复杂度为O(n log k)。 知识点4:迭代与递归 在Java中,我们可以使用迭代或递归的方式来实现这个算法。迭代通常更利于性能优化,而递归...

    求一个数组最小的两个数的下标

    例如,使用优先队列(最小堆),我们可以将数组的第一个元素放入堆中,然后依次将其他元素与堆顶元素比较,如果比堆顶元素小,则替换堆顶元素并调整堆。这样,堆顶始终保存最小的元素,堆中第二小的元素就是次小的...

    c#-Leetcode面试题解之第4题寻找两个正序数组的中位数.zip

    3. **最小堆和最大堆**:另一种常用的方法是使用两个大小为K的堆(K为较小数组的长度),一个是最小堆,存储较大数组的元素,另一个是最大堆,存储较小数组的元素。这样可以保持堆的性质,同时保证堆顶元素分别是两...

    算法-数组排序 按数组内数字大小排序 取得最大值或最小值.rar

    - 优先队列(堆):使用最大堆结构,可以快速找到最大的k个元素。 三、排序算法的时间复杂度和稳定性 时间复杂度是衡量排序算法效率的重要指标,它表示算法运行所需的基本运算次数。常见排序算法的时间复杂度范围...

    在一堆数中取得前K个最大最小的数的方法

    - **求解第k到第m大的数**:可以将问题转化为求解m-k+1个第k大的数,通常推荐使用最小堆或计数排序变体的方法,因为它们具有较低的整体复杂度。 - **快速更新最大权重**:在搜索引擎中需要实时更新权重的情况下,...

    算法:求第k小元素

    在计算机科学中,"求第k小元素"是算法设计中的一个重要问题,它涉及到排序和查找的技巧。这个问题的目标是从一个未排序或者部分排序的数组或集合中找到第k个最小的元素,其中k通常是一个正整数。这个问题在数据分析...

    python-leetcode面试题解之第215题数组中的第K个最大元素-题解.zip

    第215题是“数组中的第K个最大元素”(Find the Kth Largest Element in an Array),这是一个常见的数据结构与算法问题,考察了排序、堆和快速选择等算法知识。本题解将详细阐述如何用Python解决这个问题。 首先,...

    js代码-数组中的第K个最大元素

    快速选择是快速排序的一个变种,用于寻找数组中第K小或第K大的元素,平均时间复杂度为O(n)。它通过分治策略来选择枢轴,使得一部分元素小于枢轴,一部分大于枢轴,直到找到目标位置。 4. **计数排序法**: 如果...

    数组排序后拿出最大的几个数,并且取它们的下标,包括数组元素相同的情况

    在Java编程中,面对"数组排序后拿出最大的几个数,并且取它们的下标,包括数组元素相同的情况"这样的需求,我们需要使用特定的算法来处理。这个问题可以通过多种方法解决,这里我们将详细介绍一种常见且有效的方法:...

    几种查找数组的前K个最小值的算法.docx

    该方法首先给定一个K个大小的数组b,然后复制数组a中的前K个数到数组b中,将这K个数当成数组a的前K个最小值,对数组b创建最大堆,然后遍历数组a,比较数组a中的其他元素,如果其他元素小于数组b的最大值(堆顶),则...

    k-means对一维数组进行聚类的代码,适合初学者

    关于k-means聚类的原理可以参考这篇博客: https://blog.csdn.net/sinat_36710456/article/details/88019323 本篇只讨论基本的代码实现,由于只是对一维数组的聚类,距离公式上比较简单:distance = |a – b| 适合...

    求有N个元素的数组中前k个最大的数?(N>=k)(python实现)

    具体思路为:第一次先遍历数组找到最大的数,第二次遍历从剩下的数组中找到最大的数(在整个数组中第二大的数)…共需遍历k次,这种方法的时间复杂度为O(N*k) 方法三:综合法 该方法思路是: (1)维护一个大小为k的...

    C语言TOP-K问题(从一堆数据中找出最大的k个数或者最小的k个数)

    在C语言中,处理大数据集并找出其中最大的k个数或最小的k个数是一个常见的问题,这通常涉及到数据结构中的“堆”概念。堆是一种特殊的树形数据结构,满足以下性质:每个父节点的值要么大于等于其子节点(大顶堆),...

    几种查找数组的前K个最小值的算法.pdf

    在代码中,`QuickSelect`函数用于选取数组中第k小的元素,而`max_heapify`函数则用于维护最大堆的性质。这些实现都是算法和数据结构理论在实际编程中的体现。通过灵活运用这些工具,我们可以有效地解决查找数组前K个...

    java求第k小问题

    在Java编程语言中,"求第k小问题"是一个经典的算法问题,常见于计算机科学的排序与搜索领域。这个问题的基本需求是,给定一个整数数组或列表,找到其中的第k个最小元素,这里的k通常是从1开始的自然数。这种问题在...

    线段树和树状数组入门介绍

    树状数组通常包含三个基本操作:read返回区间[1, k]的元素和,update将索引k处的值增加v,以及find_Kth返回第k大的元素。 线段树和树状数组各有优势,线段树适用于区间最值查询,而树状数组更适合区间求和。在实际...

    POJ2092:计数排序,求第K大的元素

    【标题】"POJ2092:计数排序,求第K大的元素"是一个编程题目,主要涉及计数排序算法以及如何在数组中找出第K大的元素。计数排序是一种非基于比较的排序算法,它适用于整数排序,尤其在数据范围不大的情况下效率极高。...

    寻找第k小元素(vc)

    3. **计数排序**:如果数组中的元素范围不是特别大,可以使用计数排序预处理出每个元素出现的次数,然后根据计数结果找到第k小的元素。这种方法的时间复杂度为O(n + k),空间复杂度为O(max_val),其中max_val是数组...

Global site tag (gtag.js) - Google Analytics