1. 程式人生 > >無序序列中O(n)時間複雜度尋找最小(最大)的K個數

無序序列中O(n)時間複雜度尋找最小(最大)的K個數

一、快速排序,平均複雜度為n*logn

二、維護K個最小(最大)堆,平均複雜度為n*logK

三、類似快排的劃分方法

尋找N個數中最大的K個數,本質上就是尋找最大的K個數中最小的那個,也就是第K大的數。

可以使用二分搜尋的策略來尋找N個數中的第K大的數。對於一個給定的數p,可以在O(N)的時間複雜度內找出所有不小於p的數。

尋找第k大的元素:

#include <iostream>
using namespace std;

//快速排序的劃分函式
int partition(int a[],int l,int r)
{
    int i,j,x,temp;
    i = l;
    j = r+1;
    x = a[l];
    //將>=x的元素換到左邊區域
    //將<=x的元素換到右邊區域
    while (1)
    {
        while(a[++i] > x);
        while(a[--j] < x);
        if(i >= j) break;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    a[l] = a[j];
    a[j] = x;
    return j;
}

//隨機劃分函式<span style="color:#ff0000;">(注:也可以使用無分化中項的中項方法,或者中位數的中位數方法來劃分,不然無法達到O(n)的複雜度)
</span>int random_partition(int a[],int l,int r)
{
    int i = l+rand()%(r-l+1);//生產隨機數
    int temp = a[i];
    a[i] = a[l];
    a[l] = temp;
    return partition(a,l,r);//呼叫劃分函式
}

//線性尋找第k大的數
int random_select(int a[],int l,int r,int k)
{
    int i,j;
    if (l == r) //遞迴結束
    {
        return a[l];
    }
    i = random_partition(a,l,r);//劃分
    j = i-l+1;
    if(k == j) //遞迴結束,找到第K大的數
        return a[i];
    if(k < j)
    {
        return random_select(a,l,i-1,k);//遞迴呼叫,在前面部分查詢第K大的數
    }
    else
        return random_select(a,i+1,r,k-j);//遞迴呼叫,在後面部分查詢第K大的數
}

int main()
{
    int a[]={1,2,3,4,6,6,7,8,10,10};

    cout<<random_select(a,0,9,1)<<endl;
    cout<<random_select(a,0,9,5)<<endl;
    return 0;
}

相關推薦

無序序列O(n)時間複雜尋找()的K個數

一、快速排序,平均複雜度為n*logn 二、維護K個最小(最大)堆,平均複雜度為n*logK 三、類似快排的劃分方法 尋找N個數中最大的K個數,本質上就是尋找最大的K個數中最小的那個,也就是第K大的數。 可以使用二分搜尋的策略來尋找N個數中的第K大的數。對於一個給定的數p,

在柱狀圖矩形——O(n)時間複雜java實現

最近在刷leetcode,又碰到了這道題,想起來當時演算法有些瑕疵,所以將最新的AC程式碼更新在最上面做個對比,具體思路見註釋. public class Solution { // 思路: 主要是使用一個棧來儲存陣列元素的下標,注意是儲存‘下標’。

O(n)時間複雜內找出陣列的眾數

bool FindMostApperse(int *num,int len,int &candidate) { int count = 0; for(int i = 0;i < len;++i) { if(count == 0)

面試題:top k演算法O(n)時間複雜

在《資料結構與演算法分析--c語言描述》一書,第7章第7.7.6節中,闡述了一種在平均情況下,時間複雜度為O(N)的快速選擇演算法。如下述文字: 選取S中一個元素作為樞紐元v,將集合S-{v}分割成S1和S2,就像快速排序那樣 如果k <= |S1|,那麼第k個最小

動態規劃演算法(連續子陣列和,O(N)時間複雜O(1)空間複雜) 【更新於:2018-05-13】

這個題目最早在13年阿里筆試出現,直到前兩天面試另一家電商又出現,哎,欠的都是要還的。 這個問題的思路如下:一維陣列的下標連續的元素構成連續子陣列,求所有連續子陣列中和最大的那個子陣列。 解析:2018-11-08 1 首先這個問題要轉化為Q(n)的問題,對於Q(n)的

強大的隨機演算法-簡潔的O(n)時間複雜解決查詢第k大數問題優化演算法

之前用了個分治法用O(n)時間複雜度簡潔查詢diK大數的問題。可以參考下面部落格: 但是由於過於複雜,估計很多人都不想使用。 下面我用隨機法來解決這個問題吧,據複雜的數學分析隨機法的時間是少於4n的,而分治法反而是4n,所以其實隨機法更加優化了,而且更加重要的是更加簡單了

Manacher演算法解決長迴文子串問題---O(n)時間複雜

#include <iostream> #include <string.h> using namespace std; void Manacher(char *src) { char *str = new char[2*strlen(src)+3]; str[0]

python_lintcode_372在O(1)時間複雜刪除連結串列節點_174刪除連結串列倒數第n個節點

372在O(1)時間複雜度刪除連結串列節點 題目 給定一個單鏈表中的一個等待被刪除的節點(非表頭或表尾)。請在在O(1)時間複雜度刪除該連結串列節點。 樣例 Linked list is

連續子序列的和,時間複雜O(n)

練習題目 給定陣列 [ a0, a1, a2, …, an ] ,找出其最大連續子序列和,要求時間複雜度為 O(n),陣列包含負數。 例如:輸入 [ -2,11,-4,13,-5,-2] ,輸出 20(即 11 到 13)。 解答 關於這個問題有很多種解法,這裡介紹一種時間複雜度僅為 O(n)

長度為n的順序表L,編寫一個時間複雜O(n),空間複雜O(1)的演算法,該演算法刪除線性表所有值為X的元素

解法:用K記錄順序表L中不等於X的元素個數,邊掃描L邊統計K,並將不等於X的元素向前放置K位置上,最後修改L長度 void  del_x_1(SqList &L,Elemtype x){ int k=0; for(i=0;i<L.length;i++) {

將陣列排序,陣列所有的負整數出現在正整數前面(時間複雜O(n), 空間複雜O(1)).

<pre name="code" class="plain">#include <stdio.h> #define N 10 void swap (int *a, int i,

大子序列的和演算法-時間複雜O(n)

#include<iostream> using namespace std; int MaxSubseqSum(int ar[],int n){ int ThisSum=0,MaxSu

陣列只出現一次的數字,時間複雜O(n),空間複雜O(1)的解法

題目:一個整型數組裡除了兩個陣列外,其他的數字都出現了兩次,要找出這兩個數字。      異或運算有一個性質:任何數異或它自己,結果都是0;這樣如果題目變成只有一個數字只出現一次,其他數字均出現兩次,這樣我們從頭到尾異或陣列中的每一個數字,那麼最終的結果就是隻出現一次的數字

有1,2,....一直到n無序陣列,求排序演算法,要求時間複雜O(n),空間複雜O(1)

http://blog.csdn.net/dazhong159/article/details/7921527 1、有1,2,....一直到n的無序陣列,求排序演算法,並且要求時間複雜度為O(n),空間複雜度O(1),使用交換,而且一次只能交換兩個數。 #include &

718. Maximum Length of Repeated Subarray 字尾陣列解長公共子串 O(n log^2 n)時間複雜

題意 找最長公共子串 思路 用dp的方法很容易在O(n^2)解決問題,這裡主要討論用字尾陣列的思路解決這個問題 字尾數組裡有兩個經典的概念或者稱為資料結構,就是字尾陣列SA,以及高度陣列LCP SA陣列的定義是:將原串S所有的字尾按字典序排序

CVPR論文《100+ Times FasterWeighted Median Filter (WMF)》的實現和解析(附原始碼)。 任意半徑值濾波(擴充套件至百分比濾波器)O(1)時間複雜度演算法的原理、實現及效果 任意半徑值濾波(擴充套件至百分比濾波器)O(1)時間複雜度演算法的原理、實現及

  四年前第一次看到《100+ Times FasterWeighted Median Filter (WMF)》一文時,因為他附帶了原始碼,而且還是CVPR論文,因此,當時也對程式碼進行了一定的整理和解讀,但是當時覺得這個演算法雖然對原始速度有不少的提高,但是還是比較慢。因此,沒有怎麼在意,這幾天有幾位朋友

長遞增子序列 O nlgn時間複雜

對於一個數字序列,請設計一個複雜度為O(nlogn)的演算法,返回該序列的最長上升子序列的長度,這裡的子序列定義為這樣一個序列U1,U2...,其中Ui < Ui+1,且A[Ui] < A[Ui+1]。 給定一個數字序列A及序列的長度n,請返回最長上升子序列的長度。 測試樣例: [2,1,4

O(logN)時間複雜內求整數的N次方以及矩陣的N次方

整數N次方 假設一個整數是10,如何最快地求解10的75次方。 1. 75的二進位制數形式為1001011 2. 10的75次方=10^64 × 10^8 × 10^2 × 10^1 在這個過程中,我們先求出10^1,然後根據10^2,再根據10^2求出

合併兩個有序連結串列--實現1+2+3+....+n,時間複雜O(1)

1、合併兩個有序連結串列,合併以後的連結串列依舊有效 C語言實現 連結串列結點定義如下: typedef int DataType; typedef struct Node { DataType _data; struct Node*

長遞增子序列(兩種時間複雜演算法及其區別)+長遞減子序列(reverse)

O(n*n)//LIS+路徑回溯 O(n*n) #include <iostream> #include<cstdio> #include<stack> #i