《剑指offer》第四十题(最小的k个数)
// 面试题40:最小的k个数 // 题目:输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8 // 这8个数字,则最小的4个数字是1、2、3、4。 #include <set> #include <vector> #include <iostream> #include <functional> using namespace std; // ====================方法1==================== //使用Partition函数,利用快排思想找到前K个数 /*Random Partition*/ int RandomInRange(int min, int max) { int random = rand() % (max - min + 1) + min; return random; } void Swap(int* num1, int* num2) { int temp = *num1; *num1 = *num2; *num2 = temp; } int Partition(int data[], int length, int start, int end)//快排 { if (data == nullptr || length <= 0 || start < 0 || end >= length) throw new exception("Invalid Parameters"); int index = RandomInRange(start, end);//生成随机点 Swap(&data[index], &data[end]);//放到最后 int small = start - 1; for (index = start; index < end; ++index)//把数列中小于随机点的值放到前面 { if (data[index] < data[end]) { ++small; if (small != index) Swap(&data[index], &data[small]); } } ++small; Swap(&data[small], &data[end]);//然后把随机点放入小于它的值的后面 return small; } /*核心算法*/ void GetLeastNumbers_Solution1(int* input, int n, int* output, int k) { if (input == nullptr || output == nullptr || k > n || n <= 0 || k <= 0) return; int start = 0; int end = n - 1; int index = Partition(input, n, start, end); while (index != k - 1) { if (index > k - 1) { end = index - 1; index = Partition(input, n, start, end); } else { start = index + 1; index = Partition(input, n, start, end); } } for (int i = 0; i < k; ++i)//可见改变了输入数组 output[i] = input[i]; } // ====================方法2==================== typedef multiset<int, greater<int> > intSet;//greater函数和less相反,这个谓词 typedef multiset<int, greater<int> >::iterator setIterator;//设置迭代器 void GetLeastNumbers_Solution2(const vector<int>& data, intSet& leastNumbers, int k) { leastNumbers.clear();//清空 if (k < 1 || data.size() < k) return; vector<int>::const_iterator iter = data.begin();//vector迭代器 for (; iter != data.end(); ++iter) { if ((leastNumbers.size()) < k) leastNumbers.insert(*iter); else { setIterator iterGreatest = leastNumbers.begin();//multiset迭代器 if (*iter < *(leastNumbers.begin())) { leastNumbers.erase(iterGreatest);//删除该条目 leastNumbers.insert(*iter);//插入新的,自动排序 } } } } // ====================测试代码==================== void Test(const char* testName, int* data, int n, int* expectedResult, int k) { if (testName != nullptr) printf("%s begins: \n", testName); vector<int> vectorData; for (int i = 0; i < n; ++i) vectorData.push_back(data[i]); if (expectedResult == nullptr) printf("The input is invalid, we don't expect any result.\n"); else { printf("Expected result: \n"); for (int i = 0; i < k; ++i) printf("%d\t", expectedResult[i]); printf("\n"); } printf("Result for solution1:\n"); int* output = new int[k]; GetLeastNumbers_Solution1(data, n, output, k); if (expectedResult != nullptr) { for (int i = 0; i < k; ++i) printf("%d\t", output[i]); printf("\n"); } delete[] output; printf("Result for solution2:\n"); intSet leastNumbers; GetLeastNumbers_Solution2(vectorData, leastNumbers, k); printf("The actual output numbers are:\n"); for (setIterator iter = leastNumbers.begin(); iter != leastNumbers.end(); ++iter) printf("%d\t", *iter); printf("\n\n"); } // k小于数组的长度 void Test1() { int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 }; int expected[] = { 1, 2, 3, 4 }; Test("Test1", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int)); } // k等于数组的长度 void Test2() { int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 }; int expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; Test("Test2", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int)); } // k大于数组的长度 void Test3() { int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 }; int* expected = nullptr; Test("Test3", data, sizeof(data) / sizeof(int), expected, 10); } // k等于1 void Test4() { int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 }; int expected[] = { 1 }; Test("Test4", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int)); } // k等于0 void Test5() { int data[] = { 4, 5, 1, 6, 2, 7, 3, 8 }; int* expected = nullptr; Test("Test5", data, sizeof(data) / sizeof(int), expected, 0); } // 数组中有相同的数字 void Test6() { int data[] = { 4, 5, 1, 6, 2, 7, 2, 8 }; int expected[] = { 1, 2 }; Test("Test6", data, sizeof(data) / sizeof(int), expected, sizeof(expected) / sizeof(int)); } // 输入空指针 void Test7() { int* expected = nullptr; Test("Test7", nullptr, 0, expected, 0); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); system("pause"); return 0; }