[英]Find the kth smallest element in an unsorted array of non-negative integers
不允許修改數組(數組是只讀的)。 允許使用恆定的額外空間。
例如:A:[2 1 4 3 2] k:3
回答:2
我是按照下面的方式做的。 答案是正確的,但需要提高存儲效率。
void insert_sorted(vector<int> &B, int a,int k)
{
for(int i=0;i<k;i++)
{
if(B[i]>=a)
{
for(int j=k-1;j>i;j--)
B[j]=B[j-1];
B[i]=a;
return;
}
}
}
int Solution::kthsmallest(const vector<int> &A, int k) {
vector <int> B;
for(int i=0;i<k;i++)
{
B.push_back(INT_MAX);
}
int l=A.size();
for(int i=0;i<l;i++)
{
if(B[k-1]>=A[i])
insert_sorted(B,A[i],k);
}
return B[k-1];
}
一種可能的解決方案是二進制搜索。
設A
為輸入數組; 我們想要找到一個數字b
,使得A
中的k
項目恰好小於b
。
顯然, b
必須在[0, max(A)]
范圍內。 我們從該范圍開始進行二進制搜索。
假設我們在[lo, hi]
范圍內搜索。 令c = (lo + hi)/2
,這是中間的樞軸。 有以下三種情況:
A
小於c
的項目數小於k
。 在這種情況下,我們搜索的數字應大於c
,因此它應在范圍內(c, hi]
A
小於c
的項目數大於k
。 同樣,我們搜索的數字在[lo, c)
范圍內
A
小於c
的項目數等於k
。 在這種情況下,答案是A
中大於或等於c
的最小元素。 可以通過再次在A
進行線性搜索來找到
復雜度為O(n log m)
,其中m
是A
的最大元素。
/* assume k is 0 based, i.e. 0 <= k < n */
int kth_element(const vector<int> &A, int k){
int lo = 0, hi = *max_element(A.begin(), A.end());
while (lo <= hi){
int mid = (lo + hi) / 2;
int rank_lo = count_if(A.begin(), A.end(), [=](int i){ return i < mid;});
int rank_hi = count_if(A.begin(), A.end(), [=](int i){ return i <= mid;});
if (rank_lo <= k && k < rank_hi)
return mid;
if (k >= rank_hi)
lo = mid + 1;
else
hi = mid - 1;
}
}
盡管這並不是解決此特定問題的答案(因為它需要可修改的集合),但是有一個名為std::nth_element
的函數,該函數重新排列元素,使第k個元素位於位置k
,所有元素位於小於k
小於或等於第k個元素,其中k
是輸入參數。
這個問題不要求任何時間限制。 一個O(nk)
解決方案非常簡單,它最多迭代k
次數組,每次都丟棄一個元素(及其重復項)。
int FindKthSmallesr(const std::vector<int>& v, int k) {
// assuming INT_MIN cannot be a value. Could be relaxed by an extra iteration.
int last_min = INT_MIN;
while (k > 0) {
int current_min = INT_MAX;
for (int x : v) {
if (x <= last_min) continue;
current_min = std::min(current_min, x);
}
last_min = current_min;
for (int x : v) {
if (x == current_min) k--;
}
}
return last_min;
}
關於ideone的代碼: http ://ideone.com/RjRIkM
如果只允許恆定的額外空間,我們可以使用簡單的O(n * k)算法。
int kth_smallest(const vector<int>& v, int k) {
int curmin = -1;
int order = -1;
while (order < k) { // while kth element wasn't reached
curmin = *min_element(v.begin(), v.end(), [curmin](int a, int b) {
if (a <= curmin) return false;
if (b <= curmin) return true;
return a < b;
}); // find minimal number among not counted yet
order += count(v.begin(), v.end(), curmin); // count all 'minimal' numbers
}
return curmin;
}
可以使用的在線版本: http : //ideone.com/KNMYxA
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.