寻找数组中第k大的数

题目:有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。

给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。

测试样例:
[1,3,5,2,2],5,3

返回:
2

 

方法一:

利用冒泡排序,进行k趟排序,即可查找到第k大的数(每趟冒泡排序都寻找当前序列中的最大值)

方法二:

利用选择排序,进行k趟排序,即可查找到第k大的数(每趟选择排序都寻找当前序列中的最大值)

方法三:

利用快速排序的思想,只需找到第k大的数,不必把所有的数排好序。

思路分析:先任取一个数(找到基准值),把比它大的数移动到它的右边,比它小的数移动到它的左边。移动完成一轮后,看该数的下标(从0计数),如果刚好为length-k,则它就是第k大的数(因为移动后的基准值左边都是比它小的数,右边都是比他大的数,右边若没有元素,则说明当前基准值是第1大元素,若右边有1个元素,则说明当前基准值是第2大元素,若右边有2个元素,则说明当前基准值是第3大元素......即当前基准值右边有k-1个元素,或当前基准值的下标为length-k,则说明当前基准值是第k大元素),如果小于length-k,说明第k大的数在它右边,如果大于length-k,则说明第k大的数在它左边,取左边或者右边继续进行移动,直到找到。

代码实现:

package com.csu.marden;

public class Demo6 {
	public static void main(String[] args) {
		int [] arr={3,1,2,5,4,7,6};
		int k=2;
		System.out.println(quickSort(arr, 0, arr.length-1, k));
		
	}

	
    //使用快速排序的原理,寻找第k大的数
	public static int quickSort(int [] arr,int start,int end,int k){
		//递归结束条件
		if(start>end){
			return -1;
		}
		int i=start;
		int j=end;
		int base=arr[start];
		while(i<j){
			while(i<j && arr[j]>=base){
				j--;
			}
			while(i<j && arr[i]<=base){
				i++;
			}
			if(i<j){
				int temp=arr[j];
				arr[j]=arr[i];
				arr[i]=temp;
			}
		}
		//此时i=j,交换base元素的位置
		arr[start]=arr[i];
		arr[i]=base;
		if(i==arr.length-k){
			//查找到第k大的数字
			return arr[i];
		}
		else if(i<arr.length-k){
			//在基准值右边寻找
			return quickSort(arr, i+1, end, k);
		}else{
			//在基准值左边寻找
			return quickSort(arr, start, i-1, k);
		}
	}

}

方法四:

针对海量数据,数据量太大无法加载到内存,若采用上述方法,必须将所有数据加载到内存进行排序,尤其是快速排序,使用递归需要额外的空间开销,此时可以使用堆排序,利用较少的空间即可找到第k大的数。

思路分析:

寻找第k大的数,可以在内存中构建一个包含k个数的小顶堆(堆顶元素是最小值),然后从外存中第k+1个数据开始,依次与小顶堆的堆顶元素进行比较,若该数比堆顶元素大,则用该数替换堆顶元素,并重新构建小顶堆,重复上述操作,直到外存中的所有数据遍历完成,此时小顶堆的堆顶元素即为第k大的数。

 

 

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
寻找两个正序数组的中位可以使用归并的方式,合并两个有序数组,得到一个大的有序数组。然后找到大的有序数组的中间位置的元素,即为中位。另一种方法是使用双指针的方式,维护两个指针,初始时分别指向两个数组的下标0的位置。每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位的位置。这样可以在O(log(m+n))的时间复杂度内找到中位。 具体步骤如下: 1. 初始化指针p1和p2分别指向两个数组的起始位置0。 2. 判断两个指针所指的元素大小,较小的元素所在的指针后移一位,直到其中一个指针到达数组末尾。 3. 若两个数组的长度之和为奇,那么中位即为当前指针指向的元素; 若两个数组的长度之和为偶,那么中位为当前指针指向的元素与其下一个元素的平均值。 4. 返回中位作为结果。 需要注意的是,为了保证时间复杂度为O(log(m+n)),在每次移动指针时,应该移动的步应该是当前指针所在数组长度的一半,即k/2,其中k为两个数组的长度之和。 以下是一个示例代码,用于说明上述方法的实现: ``` int findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length; int n = nums2.length; int total = m + n; int middle = total / 2; int p1 = 0, p2 = 0; int prev = 0, curr = 0; for (int i = 0; i <= middle; i++) { prev = curr; if (p1 < m && (p2 >= n || nums1[p1 < nums2[p2])) { curr = nums1[p1++]; } else { curr = nums2[p2++]; } } if (total % 2 == 0) { return (prev + curr) / 2; } else { return curr; } } ``` 该方法可以在O(log(m+n))的时间复杂度内找到两个正序数组的中位。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [算法:寻找两个正序数组的中位。](https://blog.csdn.net/en_joker/article/details/107179641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [寻找两个正序数组的中位](https://blog.csdn.net/wulila/article/details/124483500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值