题目:
输入n个整数,找出其中最小的k个数,例如输入{ 4, 5, 1, 6, 2, 7, 3, 8 }这8个数,则最小的4个数字是{1,2,3,4}。
方法一:
时间复杂度为O(nlongn)且改变了原来数组,不推荐。
分析:首先通过快速排序算法对数组元素进行排序,然后依次输出其中的前k个数。
代码《略》
方法二:
分析:使用Partation函数,使时间复杂度为O(n),如果基于数组的第K个数字来调整,使得比第K个数字小的所有数字都位于数组的左边,比第K个数字大的所有数字都位于数组的右边。这样调整之后,位于数组中左边的k个数字就是最小的k个数字。
注意:
- 输出的这k个数字不一定是排序的;
- 原始数组发生了改变!
源代码如下:
#include<iostream>
#include<cstdlib>
using std::cout;
using std::endl;
class ThrowError{};
void show(int *arr, int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void Swap(int *m, int *n)
{
int temp = *m;
*m = *n;
*n = temp;
}
//返回一个数组下标,该下标左边的数字都是小于该下标对应的值,右边的数字都大于该下标所对应的值
int Partiton(int *arr, int length, int start, int end)
{
if (arr == NULL || length <= 0 || start < 0 || end >= length)
throw ThrowError{};
int index = rand() % (end - start + 1) + start;
Swap(&arr[index], &arr[end]);
int small = start - 1;
for (int j = start; j < end; ++j)
{
if (arr[j] < arr[end])
{
++small;
if (small != j)
Swap(&arr[small], &arr[j]);
}
}
++small;
Swap(&arr[small], &arr[end]);
return small;
}
void GetLeastNumbers(int *arr, int n, int *output, int k)
{
if (arr == NULL || n <= 0 || output == NULL || k <= 0 || k > n)
return;
int start = 0;
int end = n - 1;
int index = Partiton(arr, n, start, end);
while (index != k - 1)
{
if (index < k - 1)//说明index在k的左边,需要对右边进行递归
{
start = index + 1;
index = Partiton(arr, n, start, end);
}
else//说明index在k的右边,需要对左边进行递归
{
end = index - 1;
index = Partiton(arr, n, start, end);
}
}
for (int i = 0; i < k; i++)
{
output[i] = arr[i];
}
}
void test11()
{
int arr[] = { 4, 5, 1, 6, 2, 7, 3, 8 };
int output[4] = { 0 };
GetLeastNumbers(arr, 8, output, 4);
show(output, 4);
}
int main()
{
test11();
system("pause");
return 0;
}
运行结果如下:
1 2 3 4
请按任意键继续. . .
方法二:
源代码如下:
#include<iostream>
#include<set>
#include<vector>
#include<functional>
using std::endl;
using std::cout;
using std::vector;
using std::multiset;
using std::greater;
void GetLeastNumbers2(const vector<int> &vec, multiset<int, greater<int>> &leastNumbers, size_t k)
{
if (vec.empty() || vec.size() < k)
return;
leastNumbers.clear();
for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter)
{
if (leastNumbers.size() < k)
leastNumbers.insert(*iter);
else
{
auto leastIter = leastNumbers.begin();
if (*leastIter > *iter)
{
leastNumbers.erase(*leastIter);
leastNumbers.insert(*iter);
}
}
}
}
void test21()
{
vector<int> vec = { 4, 5, 1, 6, 2, 7, 3, 8 };
multiset<int, greater<int>> leastNumbers;
GetLeastNumbers2(vec, leastNumbers, 4);
for (auto iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter)
cout << *iter << " ";
cout << endl;
}
int main()
{
test21();
system("pause");
return 0;
}
运行结果:
4 3 2 1
请按任意键继续. . .