题目:
输入n个整数,找出其中最小的K个数。
边界条件及异常:
n小于k,是否会有相同的数字
思路:
方法一:
先进行排序,然后输出最小的K个数
注意:会改变原来的数组
时间复杂度:O(nlgn)
空间复杂度:O(1)
方法二:
用额外的K个空间来存最小的K个数,再往后如果有小于这K个数的,按顺序插进来,并将较大的移出去。
用带排序的hash表(map和set带自动排序功能)来存储,插入操作时间复杂度O(lgK)
时间复杂度:O(nlgK)
空间复杂度:O(K)
#include <iostream> #include <vector> #include <queue> #include <string> #include <stack> #include <algorithm> #include <hash_set> //for hashtable #include <hash_map> #include <set> using namespace std; void getMinKNums(vector<int> nums, int k, set<int> &result) { int size = nums.size(); if (size < k) return; for (int i = 0; i < size; ++i) { if (i < k) result.insert(nums[i]); else { set<int>::iterator it = result.end(); --it; if (nums[i] < *it) { result.erase(it); result.insert(nums[i]); } } } } int main() { int arr[] = { 6, 7, 9, 8, 5, 4, 1, 2, 3 }; vector<int> nums(arr, arr + 9); set<int> result; getMinKNums(nums, 4, result); set<int>::iterator it = result.begin(); for (; it != result.end(); ++it) cout << *it << " "; cout << endl; return 0; }
时间复杂度:O(n)
#include <iostream> #include <vector> #include <queue> #include <string> #include <stack> #include <algorithm> #include <hash_set> //for hashtable #include <hash_map> #include <set> #include <ctime> using namespace std; int RandomInRange(int start, int end) { srand(time(0)); return (rand() % (end-start) + start); } int Partition(vector<int> &data, int start, int end) { int length = data.size(); if (length <= 0 || start < 0 || end >= length) throw new std::exception("Invalid Parameters"); int index = RandomInRange(start, end); swap(data[index], data[start]); //将随机中枢交换的第一个 int pivotkey = data[start]; //取第一个为中枢,且将中枢值存下来 while (start < end) { while (start < end && data[end] >= pivotkey) --end; data[start] = data[end]; while (start < end && data[start] <= pivotkey) ++start; data[end] = data[start]; } data[start] = pivotkey; return start; } void getMinKNums(vector<int> nums, int k, vector<int> &result) { int size = nums.size(); if (size == 0 || size < k || k <= 0) return; int end = size - 1; int start = 0; int index = Partition(nums, start, end); while (index != k - 1) { if (index > k - 1) { end = index - 1; index = Partition(nums, start, end); } else { start = index + 1; index = Partition(nums, start, end); } } for (int i = 0; i < k; ++i) result.push_back(nums[i]); } int main() { int arr[] = { 6, 7, 9, 8, 5, 4, 1, 2, 3 }; vector<int> nums(arr, arr + 9); vector<int> result; getMinKNums(nums, 4, result); vector<int>::iterator it = result.begin(); for (; it != result.end(); ++it) cout << *it << " "; cout << endl; return 0; }
注意:方法二除了有不改变原来数据外,还有适合海量数据的输入。假设题目要求重海量数据中找出最小的K个数字,由于内存大小的限制,不可能把海量数据一次性全部载入内存。这时候可以借助辅助存储空间中每次读入一个数字。