2014-05-10 21:56
原题:
Suppose you get number of unique users every second from bing For eg, 2,4,5,1,2,etc You need to write a web service method , such that it takes the input n, which return lowest n unique number from the list of unique numbers. For eg, if n is 3 then you need to return 2,1,2
题目:从n个数里找出m个最小的数。
解法1:题目虽然没有要求结果是否有序,也没有说算法是否是在线的。那么肯定是有两种解法的。第一种就是O(n * log(m))的最大堆法。能提供有序的结果。如果要求在线算法的话,堆仍能满足要求。
代码:
1 // http://www.careercup.com/question?id=5943729928011776 2 #include <iostream> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 7 template <class T> 8 struct myless { 9 bool operator () (const T &x, const T &y) { 10 return x < y; 11 }; 12 }; 13 14 int main() 15 { 16 int val; 17 int n, k; 18 int i; 19 // max heap 20 priority_queue<int, vector<int>, myless<int> > q; 21 vector<int> v; 22 23 while (cin >> n >> k && (n > 0 && k > 0)) { 24 k = k < n ? k : n; 25 for (i = 0; i < k; ++i) { 26 cin >> val; 27 q.push(val); 28 } 29 30 for (i = k; i < n; ++i) { 31 cin >> val; 32 if (q.top() > val) { 33 q.pop(); 34 q.push(val); 35 } 36 } 37 while (!q.empty()) { 38 v.push_back(q.top()); 39 q.pop(); 40 } 41 reverse(v.begin(), v.end()); 42 43 cout << '{'; 44 for (i = 0; i < k; ++i) { 45 i ? (cout << ' '), 1 : 1; 46 cout << v[i]; 47 } 48 cout << '}' << endl; 49 50 v.clear(); 51 } 52 53 return 0; 54 }
解法2:快速选择算法可以在O(n)时间找出第k大的数,不过写法复杂,并且运行的实际效率由于常系数很大,递归不稳定等缺点,使得这算法很多时候只是看上去很美。利用这个算法得到第m大的数之后,再扫描一次整个数组就能得到最小的m个数了。这个算法不能在线进行,因为快速选择算法的思想源自快速排序,是不稳定的内存排序算法。
代码:
1 // http://www.careercup.com/question?id=5943729928011776 2 #include <algorithm> 3 #include <iostream> 4 #include <vector> 5 using namespace std; 6 7 const int CUT_OFF = 3; 8 9 int medianThree(vector<int> &v, int ll, int rr) 10 { 11 int mm = (ll + rr) / 2; 12 13 if (v[ll] > v[mm]) { 14 swap(v[ll], v[mm]); 15 } 16 if (v[ll] > v[rr]) { 17 swap(v[ll], v[rr]); 18 } 19 if (v[mm] > v[rr]) { 20 swap(v[mm], v[rr]); 21 } 22 swap(v[mm], v[rr - 1]); 23 return v[rr - 1]; 24 } 25 26 void quickSelect(vector<int> &v, int ll, int rr, int k) 27 { 28 // reference from "Data Structure and Algorithm Analysis in C" by Mark Allen Weiss. 29 int pivot; 30 int i, j; 31 32 if (ll + CUT_OFF <= rr) { 33 pivot = medianThree(v, ll, rr); 34 i = ll; 35 j = rr - 1; 36 37 while (true) { 38 while (v[++i] < pivot); 39 while (v[--j] > pivot); 40 if (i > j) { 41 break; 42 } 43 swap(v[i], v[j]); 44 } 45 swap(v[i], v[rr - 1]); 46 47 if (k < i) { 48 return quickSelect(v, ll, i - 1, k); 49 } else if (k > i) { 50 return quickSelect(v, i + 1, rr, k); 51 } 52 } else { 53 for (i = ll; i <= rr; ++i) { 54 for (j = i + 1; j <= rr; ++j) { 55 if (v[i] > v[j]) { 56 swap(v[i], v[j]); 57 } 58 } 59 } 60 } 61 } 62 63 int main() 64 { 65 vector<int> v; 66 vector<int> res; 67 int n, k; 68 int i; 69 int k_small, count; 70 71 while (cin >> n >> k && (n > 0 && k > 0)) { 72 v.resize(n); 73 for (i = 0; i < n; ++i) { 74 cin >> v[i]; 75 } 76 77 // find the kth smallest number 78 // this will change the order of elements 79 quickSelect(v, 0, n - 1, k - 1); 80 k_small = v[k - 1]; 81 count = k; 82 for (i = 0; i < n; ++i) { 83 if (v[i] < k_small) { 84 --count; 85 } 86 } 87 for (i = 0; i < n; ++i) { 88 if (v[i] < k_small) { 89 res.push_back(v[i]); 90 } else if (v[i] == k_small && count > 0) { 91 res.push_back(v[i]); 92 --count; 93 } 94 } 95 96 cout << '{'; 97 for (i = 0; i < k; ++i) { 98 i ? (cout << ' '), 1 : 1; 99 cout << res[i]; 100 } 101 cout << '}' << endl; 102 103 v.clear(); 104 res.clear(); 105 } 106 107 return 0; 108 }