【28】一个无序的序列查找第K大的数

题目:给定一个无序序列和一个数k,求这个无序序列中第K大的数

分析:

方案一:最朴素的方法利用快速排序然后找到第k个数,时间复杂度O(nlogn)

方案二:根据快速排序中的partition方法,每次可以把一个序列分成两个部分,左边全部小于等于基准,右边的全部大于等于基准。如果partition方法中基准的位置刚好是第k个则可以直接得多这个数,如果大于k说明在左边,如果小于k说明在右边。

              利用这个方法每次可以将序列不断的划分直至找到这第k个数, 因为partition函数的时间复杂度最大为O(n),而我们每次都可以把序列分成一半,因此总的时间复杂度还是O(n)。

              时间复杂度的证明:

              1. 假设总的元素个数有n个,则

                  第一次枚举n个数

                  第二次枚举n/2

                  第三次枚举n/4

                  ...................1

              2. 则总的时间为n+n/2+n/4+....+1 <= 2n,因此时间复杂度为O(n)

举例:

例如无序序列为0 9 -1 6 7 3 5,k为3则第k大的数为6。

实例代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

//Partition方法
int Partition(int *arrNum, int l, int r){
	//不合法数据
	if(arrNum == NULL || l > r){
        return -1;
    }
    int mid = (l+r)>>1;
	swap(arrNum[mid], arrNum[r]);
	int leftSeqIndex = l;
	//枚举区间
	for(int i = l; i < r; i++){
	    if(arrNum[i] < arrNum[r]){
           if(i > leftSeqIndex){
		   		swap(arrNum[i], arrNum[leftSeqIndex]);
   		   }
   		   ++leftSeqIndex;
		}
    }
    //基准交换回来
	swap(arrNum[leftSeqIndex], arrNum[r]);
	return leftSeqIndex;
}

//求第k大的数
int GetNumber(int *arrNum, int n, int k){
	//输出-1表示不合法
	if(arrNum == NULL || n <= 0 || k <= 0 || k > n){
        return -1;
    }
    //第k大的数等价于找第n-k+1小的数
	k = n-k+1;
	int l = 0;
	int r = n-1;
	while(l <= r){
	    int index = Partition(arrNum, l, r);
		if(index+1 == k){ //找到
            return arrNum[index];
        }
        else if(index+1 < k){ //在右边序列找
		    l = index+1;
	    }
	    else{ //在左边序列找
	        r = index-1;
	    }
	}
} 

int main(){
   int arrNum[] = {0,9,-1,6,7,3,5};
   int value = GetNumber(arrNum, 7, 3);
   if(value == -1){
       cout<<"no found number";
   }
   else{
       cout<<value<<endl;
   }

   getchar();
   return 0;
}

/*
输出
6
*/ 
时间: 2024-10-01 19:52:51

【28】一个无序的序列查找第K大的数的相关文章

c语言-C语言 给定一个整数序列和一个数k,求这个序列中第k小的数。

问题描述 C语言 给定一个整数序列和一个数k,求这个序列中第k小的数. C语言 给定一个整数序列和一个数k,求这个序列中第k小的数. 我的程序 #include<stdio.h> int n[10000]; void Nok() { int i=0,j=0,t,k,q=0; char c; scanf("%d",&n[i++]); c=getchar(); while(c!='n') { scanf("%d",&n[i++]); c=ge

【算法与数据结构】在n个数中取第k大的数(基础篇)

(转载请注明出处:http://blog.csdn.net/buptgshengod) 题目介绍           在n个数中取第k大的数(基础篇),之所以叫基础篇是因为还有很多更高级的算法,这些以后再讨论.本文用两种最基本的方法来解决这个问题.使用java语言描述.例子是十个数中取第三大的. 算法一              用冒泡法将n个数从大到小排序,再取第k大. public class test { public static void main(String []args) { i

C#递归算法寻找数组中第K大的数_C#教程

1.概述 国人向来喜欢论资排辈的,每个人都想当老大,实在当不成,当个老二,老三,老K也不错,您一定看过这样的争论: 两个人吵架,一个人非常强势,另外一个忍受不住了便说:"你算老几呀?",下面就通过这篇文章就是要解决找出老几的问题! 2.应用场景 在向量V[first,last)中查找出第K大元素的值 3.分析 如果利用排序算法将向量V排好序,那么第K大元素就是索引为v.length-k的元素了,这样能解决问题,但效率不高,因为这相当于为了歼灭敌人一个小队而动用了我们全军的力量,得不偿失

无序整数数组中找第k大的数

方法一:基于快排 1 /* 2 基于区间快排的第K小算法 ,输出a[k-1]即可,O(n*logn):每次只对后半部分递归便可把复杂度降到O(n) 3 主要思路是每次随机在数组中选取一个元素p,利用这个元素将数组分成两部分,比p小的元素在分好的数组左边,p和比p大的元素在数组右边, 4 根据k值选择在数组左半或者右半部分继续递归执行查找. 5 */ 6 #include <iostream> 7 #include <cstring> 8 #include <vector>

【29】求无序序列中最小k个数

题目:给定一个无序序列和一个数k,求最小k个数(不要求数字有序) 分析: 方案一:最朴素的方法是利用快速排序,然后直接输出最小k个数,时间复杂度为O(nlogn) 方案二:利用快速排序的partition函数的性质,根据基准的性质,每次可以把序列分成两个部分,左边序列全部小于等于基准的值,右边序列全部大于等于序列的值.               只要找到基准的位置为刚好为第k的位置,则序列前面即为最小k个数.和找第k大的数其实是一个性质的,时间复杂度都是O(n).               

《程序设计解题策略》——第1章 利用树型数据关系的解题策略 1.1 利用划分树求解整数区间内第k大的值

第1章 利用树型数据关系的解题策略 树是一个具有层次结构的集合,一种限制前件数且没有回路的连通图.在现实生活和程序设计的竞赛试题中,许多问题的数据关系呈树型结构,因此有关树的概念.原理.操作方法和一些由树的数据结构支持的算法,一直受到编程者的重视,被广泛应用于解题过程.在本章里,我们将介绍利用树型数据关系解题的七种策略: 1) 利用划分树求解整数区间内第k大值. 2) 利用最小生成树及其扩展形式(最优比率生成树.最小k度生成树.次小生成树)计算有权连通无向图中边权和满足限制条件的最优生成树. 3

两个有序数组中查找第K大数

题目:两个数组A.B,长度分别为m.n,即A(m).B(n),分别是递增数组.求第K大的数字.   方法一: 简单的办法,使用Merge Sort,首先将两个数组合并,然后在枚举查找.这个算法的时间复杂度是O(m+n).空间复杂度也是O(M+n). 这个方法其实没有考虑到有第K大数为两个相同数字的情况.   方法二: 这里需要两个前提条件, 1.如果K是中位数,则(M+n)是奇数还是偶数是有关系的.如果是奇数,那么中位数唯一,如果是偶数就有两个中位数,可以随便取一个. 2.如果找到的第K大数是x

python查找第k小元素代码分享_python

复制代码 代码如下: # -*- coding: utf-8 -*- from random import randintfrom math import ceil, floor def _partition(A, l, r, i):    """以A[i]为主元划分数组A[l..r],使得:    A[l..m-1] <= A[m] < A[m+1..r]    """    A[i], A[r] = A[r], A[i] # i交

序列化-java中一个没有被序列的对象,想保存到文件上,有没有办法?

问题描述 java中一个没有被序列的对象,想保存到文件上,有没有办法? 在java中,得到了一个对象,这个对象的类不是我定义的,没有序列化,我有没有办法将这个对象写到文件上,下次用的时候读出这个对象? 解决方案 没有序列化是有原因的,有些对象并不能被序列化.比如我们用一个对象来关联一个进程,实现对操作系统进程操作的包装.这个对象包含进程id这样的字段,以及诸如复制进程.停止进程这样的方法.那么这样的对象就不能序列化. 因为序列化没有意义.你将这个对象的存储全部dump下来,重新开机,这个进程id