快速排序區間K大數查詢

2021-09-08 01:16:47 字數 2530 閱讀 6324

題目

問題描述

給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。

輸入格式

第一行包含乙個數n,表示序列長度。

第二行包含n個正整數,表示給定的序列。

第三個包含乙個正整數m,表示詢問個數。

接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序列元素從1開始標號。

輸出格式

總共輸出m行,每行乙個數,表示詢問的答案。

樣例輸入

51 2 3 4 5

21 5 2

2 3 2

樣例輸出42

資料規模與約定

對於30%的資料,n,m<=100;

對於100%的資料,n,m<=1000;

保證k<=(r-l+1),序列中的數<=106。

題解

快排的原理:利用快速排序將無序序列轉換為有序序列的過程中,經過多次的劃分;(這裡假定進行降序排列)在每一次的劃分中,在序列中找到乙個樞軸(pivot),劃分的結果是 pivot 左邊的數均比它大,右邊的數均比它小;然後對子序列進行同樣的操作,遞迴進行、直到所有子串行有序為止。

改造:我們的目標是找到第k大的數,若在一次劃分之後、pivot左邊的數(加上它本身)共有k個,那麼pivot位置上的數就是我們要找的第k大的數;其一:我們不必要求前k-1大的數有序,所以不必繼續進行遞迴劃分;其二:每一次的劃分都將原序列分為左、右兩個子串行,快排演算法需要對這兩個子串行都繼續進行遞迴的劃分,而在這裡我們只需要根據情況(具體看演算法步驟)選擇乙個子串行繼續劃分即可;因此這種求第k大的數演算法的時間複雜度小於快速排序的複雜度,為o(n*logk)

演算法步驟:經過一次劃分(partition)之後,樞軸pivot將原序列劃分為兩個部分:s和t [即原序列變為(s t)、pivot包含在子串行s中、注意使用降序排序],會出現下列三種情況:

1.子串行s中有k個數,此時pivot位置即為第k大的數,演算法結束

2.子串行s中的數字個數小於k,假設個數為l,則需要子串行t中繼續遞迴劃分出來前(k-l)個數

3.子串行s中的數字個數大於k,則需要子串行s中繼續遞迴劃分出來前k個數

**:

#include

#include

#include

#include

using

namespace std;

/*快速排序的一次劃分*/

intpartition

(int a,

int low,

int high)

a[i]

= a[j]

;while

(i>=x)

a[j]

= a[i];}

a[i]

= x;

return i;

}/* 降序排序,當一次劃分之後、pivot左邊的數(包括它本身)恰為k個時,停止劃分*/

void

find_kmax

(int a,

int low,

int high,

int k)

else

if(len > k)}}

intmain()

;int len =

sizeof

(arr)

/sizeof

(int);

// 求陣列長度

int l, r, k;

// 區間為[l, r],從1開始

scanf

("%d %d %d"

,&l,

&r,&k)

;int a[

100]

;memcpy

(a, arr,

sizeof

(arr));

// 將arr陣列的元素copy到a陣列中,這麼做是為了避免破壞原陣列、能夠進行多次不同區間的查詢

find_kmax

(a, l-

1, r-

1, k)

;// 注意區間下標與陣列下標的轉換

printf

("%d\n"

, a[l-

1+ k-1]

);// 注意第k大的數在陣列a中的位置!

return0;

}

題解二:學了快速排序後的另外一種解法:

#include

#include

using namespace std;

const

int n=

1e6+10;

int n,k,q[n]

;void

quick_sort

(int q,

int l,

int r)

quick_sort

(q,l,j)

;quick_sort

(q,j+

1,r);}

intmain()

}return0;

}

區間K大數查詢

問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序...

區間k大數查詢

問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序...

區間k大數查詢

問題描述 給定乙個序列,每次詢問序列中第 l個數到第 r個數中第 k大的數是哪個。輸入格式 第一行包含乙個數 n,表示序列長度。第二行包含 n個正整數,表示給定的序列。第三個包含乙個正整數 m,表示詢問個數。接下來m行,每行三個數 l,r,k 表示詢問序列從左往右第 l個數到第 r個數中,從大往小第...