首页 > 其他分享 >寻找无序数组中第K大的数

寻找无序数组中第K大的数

时间:2023-04-22 16:25:09浏览次数:29  
标签:right int S1 无序 寻找 数组 集合 基数 left

问题叙述:

从array[1, n]这n个数中,找出第k大的数。

输入:

5
3 1 2 4 5
2

输出:

4

问题思路:

把第一个数设为基数e,并将剩下的数划分为两个集合:比e大或相等的数的集合为S1,比e小的数的集合为S2。
如果S1大小大于等于k,说明第k大的数属于S1这个集合;如果S1大小小于k,说明k在S2中;如果k=S1,说明找到了第k大的数。
这样下来,我们把在原来的数组中找出第k大的数分成了好几个子问题,就可以使用递归的方法来解决问题。

在当前递归中,我们把最左边的数设为l,最右边的数设为r。
开一个死循环来划分集合。在划分集合的过程中,设置一个变量left寻找第一个比基数小的数,right寻找从右往左第一个比基数大的数,然后交换s[left]和s[right],这样就保证数组中l到left和right到r符合我们的要求。继续划分,直到left和right相遇。
接着,讲s[l]和s[left-1]交换,这样基数e左边都比e小,右边都比e大。(left之前和right相遇了,而且之前找基准的条件中left移动到比e大时才截止,所以left-1才是S1的右边界)
以下是划分集合的代码:

int e = s[left]; //取首位为基数
int l = left, r = right;

while (1)    {    //序列中比基数大的排左边,小的排右边
    while ((left <= right) && (e <= s[left]))
        left++;
    while ((left < right) && (e > s[right]))
        right--;
    if (left < right)    {
        Swap(&s[left], &s[right]);
    } else    {
        break;
    }
}
Swap(&s[left - 1], &s[l]); //将基数换到两集合之间

 

之后就是怎么递归的问题了。 划分完成后,k就可以成为该进行到哪个集合中继续解决子问题的标准。
left-l-1如果大于等于k,即k在S1中,那么就要在S1中进行;如果left-l-1,那么在S2中进行;如果等于k-1,说明e刚好是第k大的数,返回。

完整函数如下:

int findKthLargest(int s[], int k, int left, int right)	{
	int e = s[left]; //取首位为基数
	int l = left, r = right;

	while (1)	{	//序列中比基数大的排左边,小的排右边
		while ((left <= right) && (e >= s[left]))
			left++;
		while ((left < right) && (e < s[right]))
			right--;
		if (left < right)	{
			Swap(&s[left], &s[right]);
		} else	{
			printf("%d %d\n", left, right);
			break;
		}
	}
	Swap(&s[left - 1], &s[l]); //确保比基数小的数在比基数大的数左边
	if ((left - l - 1) >= k)	{//left - l - 1代表了比基数小的集合的大小
		return findKthLargest(s, k, l, left - 2);
	} else if ((left - l - 1) < k - 1)	{//左边集合大小小于k-1那么表明第k大的数在右边的集合
		return findKthLargest(s, k - (left - l - 1) - 1, left, r);
	} else	{//如果刚好相等那么说明找到了第k大的数
		return e;
	}
}

标签:right,int,S1,无序,寻找,数组,集合,基数,left
From: https://www.cnblogs.com/kgdy-wwy-mfkd/p/17343281.html

相关文章

  • vector动态数组库
    #include<vector>usingnamespacestd;vector<int>vec1;//定义一个空的vector,元素类型为intvector<int>vec2(10);//定义一个大小为10的vector,元素类型为int,初始值为0vector<int>vec3(10,1);//定义一个大小为10的vector,元素类型为int,初始值为1vector<int>vec4={1,2,......
  • x64逆向——MT、MT在release和debug下的四种模式寻找main入口
    vs代码生成四种模式:MT选项:链接LIB版的C和C++运行库。在链接时就会在将C和C++运行时库(LIBCMT.LIB、LIBC.LIB)集成到程序中,程序体积会变大。MTd选项:LIB的调试版。MD选项:使用DLL版的C和C++运行库,这样在程序运行时会动态的加载对应的DLL,程序体积会减小,缺点是在系统没有对应DLL时程序无......
  • 剑指Offer——03.数组中重复的数字(c语言)
    title:剑指Offer03.数组中重复的数字(c语言)找出数组中重复的数字。在一个长度为n的数组nums里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例1:输入:[2,3,1,0,2,......
  • 牛客网——数组中出现次数超过一半的数字
    title:牛客网——数组中出现次数超过一半的数字题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。示例:输入[1,2,3,2,2,2......
  • 力扣——240.搜索二维数组II(c语言)
    title:力扣——240.搜索二维数组II(c语言)同《剑指offer》04题目描述:编写一个高效的算法来搜索mxn矩阵matrix中的一个目标值target。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。示例1:输入:matrix=[[1,4,7,11,15],[2,5,8,12,19],......
  • 二维数组
    #define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(void){ intarr[4][3]= { {12,23,43}, {22,43,55}, {45,57,76}, {54,53,79} }; intsum=0; inti,j; for(i=0;i<3;i++) { for(j=0;j<4;j++) {  sum+=ar......
  • c 数组名和指针的区别
    关于c中数组名和指针的区别我写了一下程序进行测试并就自己的理解做了详细的解释,供自己以后复习,大佬批评指正和需要的网友参考学习。环境:gcc(mingw或cygwin)代码:1#include<stdlib.h>2intmain(intargc,charconst*argv[])3{4intarr[10]={23456,3,4,5,6,......
  • 【DP】LeetCode 718. 最长重复子数组
    题目链接718.最长重复子数组思路分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律在数组的动态规划问题中,一般dp[i]都是表示以nums以第i个元素组成(即nums[i-1])的状态;dp[i][j]分别表示以nums1前i个元素(......
  • C 语言数组操作
    -1.初始化: ```cintarr[5]={1,2,3,4,5};//初始化为1,2,3,4,5intarr[5]={0};//初始化为0``` 2.访问: ```cintarr[5]={1,2,3,4,5};inta=arr[0];//获取第一个元素的值``` 3.遍历: ```cintarr[5]={1,2,3,4,5};for(inti......
  • day52 300.最长递增子序列 | 674. 最长连续递增序列 | 718. 最长重复子数组
    给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示例1:输入:nums=[10,9,2,5,3,7,101,18]输出:4解释:最长递增子序列是[2,3,7,101......