题目描述:给定一个数组,输出该数组前K小数(无需排序)
示例:
Input: nums = {38, 61, 7, 87, 81, 18, 50, 55, 90, 26} K = 7
Output: result = {7, 18, 26, 38, 50, 55, 61}
题解:
这道题目有两种解题方法,一是使用排序的算法让数组从小到大排好序,然后依次输出数组的前K个整数。
这样的做法对人而言虽然简单可操作性,但因为题目没有对数组排序的要求,使用排序算法无疑让计算机做了额外的工作。
另一种“偷懒”的做法是使用分治的思想,将原来的大数组不断地按照要求划分成更小的数组,最后得到一个长度为K的子数组,且该子数组内的所有元素的值都小于不在这个子数组内的元素的值。
算法的核心是,对于一个数组,选定数组第一个元素为pivot,然后遍历该数组,分别将值小于pivot、等于pivot、大于pivot的元素存放在数组l、m、r内,并计算三个数组的元素值分别为a、b、c
进行判断:
1.若K<=a,则前k小数全部落在数组l内,则继续对l进行递归调用,参数K不变
2.若K>a+b,则前k小数包括了数组l、m的全部元素,还有部分在r内,则对r进行递归调用,参数K变为K-a-b,然后将返回的数组与l、m合并
3.其他情况,说明第K小数恰好在m内,则将l、m合并
源代码:
vector<int> partition(vector<int> v, int k) {
if (v.size() <= 1) return v;
vector<int> l, m, r;
int pivot = v[0];
for (int i = 0; i < v.size(); i++) {
if (v[i] < pivot) l.push_back(v[i]);
if (v[i] == pivot) m.push_back(v[i]);
if (v[i] > pivot) r.push_back(v[i]);
}
int a = l.size();
int b = m.size();
int c = r.size();
if (k <= a) return partition(l, k);
else if (k > a + b) {
vector<int> rr = partition(r, k - a - b);
l.insert(l.end(), m.begin(), m.end());
l.insert(l.end(), rr.begin(), rr.end());
return l;
}
else {
l.insert(l.end(), m.begin(), m.end());
return l;
}
}