算法练习——前K小数

来源:互联网 发布:阿里云smtp不能发邮件 编辑:程序博客网 时间:2024/05/17 03:34

题目描述:给定一个数组,输出该数组前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;}}