23、数组中未出现的最小正整数
【2018统考真题】给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。
例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。
要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之 处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
示例
输入:{-5, 3, 2, 3}
输出:1
说明:数组中未出现的最小正整数就是1
思路
可以直接提取这样几个关键词
- 使用数组,求未出现的最小正整数
- 看到数组,是不是想到是否有序
- 时间+空间尽可能高效
题目已经要求尽可能时间上高效,那本题就采用哈希法,典型的时间换空间的解法,用一个哈希表来记录待查找数组中每一个元素出现的次数,再从哈希表中查找次数为0的元素,该元素的key值就为最小正整数。
具体步骤:
- 遍历待查找数组,并用哈希表record记录下每个元素出现的次数,数组中不存在的元素默认出现次数为0。
- 从res = 1开始向后遍历,并以res作为哈希表record的key值,判断
record[res]的值,如果为0,则找到了最小正整数,否则继续遍历下去。 - 返回最后结果res。
具体实现
哈希法
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
/**
* @function 找出数组中未出现的最小正整数
* @param arr vector数组容器 待查找数组
* @return 整型 该数组未出现的最小正整数
*/
int FindMinPI(vector<int> arr) {
unordered_map<int, int> record; // 辅助的记录表
int res = 1; // 数组中未出现的最小整数
for (int val : arr) record[val]++; // 记录数组中每个元素出现次数
while (record[res]) res++; // 找出最小正整数,record中出现次数为0就是
return res;
}
//测试一下
int main() {
vector<int> arr = {-5, 3, 2, 3}; // 数据1
// vector<int> arr = { 1, 2, 3 }; // 数据2
int res = FindMinPI(arr);
cout << "该数组中未出现的最小正整数为:" << res;
return 0;
}
运行结果
复杂度
- 时间复杂度O(n)--- 遍历了整个数组,其中n为数组的长度
- 空间复杂度O(n)--- 辅助数组的大小n,其中n为数组的长度