在非负整数的未排序数组中查找第 k 个最小元素
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)
-
小于
c
A
中的项目数等于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
相关文章:
- 在对向量中查找元素的索引
- 在链接列表中查找元素 - C++
- 在数组中查找元素,如果找到则返回Find,否则返回not Find
- 在给定元素在螺旋上的位置的情况下,在二维数组中查找元素
- 用于查找元素的数据结构
- 为什么在查找元素时需要使用 set.find(x) != set.end()
- 在二叉搜索树中查找元素
- 二进制搜索不变以查找元素的首次出现
- 迭代列表以查找元素的出现.代码问题
- 从单链接列表(从尾部)中查找元素
- iMacro 查找元素
- 在向量数组中查找元素
- 如何在二叉搜索树中查找元素
- 如何在字符右侧的QString中查找元素
- 在Vector中查找元素对
- 如何在运行时在boost::fusion::vector中查找元素
- 在 stl 堆栈 cpp 中查找元素
- 在向量中查找元素并将其删除
- 如何在动态数组中查找元素的数量
- 在数组中查找元素,然后使用指针进行交换