开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 22 天,点击查看活动详情
Day51 2023/02/25
难度:简单
题目
给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。 要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用 C 或 C++语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间和空间复杂度。
示例1
输入:{-5, 3, 2, 3}
输出:1
说明:数组中未出现的最小正整数就是1
示例1
输入:{1, 2, 3}
输出:4
说明:数组中未出现的最小正整数就是4
思路
题目已经要求尽可能时间上高效,那本题就采用哈希法,典型的时间换空间的解法,用一个哈希表来记录待查找数组中每一个元素出现的次数,再从哈希表中查找次数为0的元素,该元素的key值就为最小正整数。
具体步骤:
- 遍历待查找数组,并用哈希表record记录下每个元素出现的次数,数组中不存在的元素默认出现次数为0。
- 从res = 1开始向后遍历,并以res作为哈希表record的key值,判断
record[res]的值,如果为0,则找到了最小正整数,否则继续遍历下去。 - 返回最后结果res。
关键点
- 要理解为什么从1开始向后连续遍历,例如:一串连续的正整数序列:1 2 3 4 5 6,其中抽走哪一个,哪一个就为这串序列中未出现的最小正整数,本题同理,相当于用record记录了哪一个元素被抽走。
算法实现
c++代码实现-哈希法
#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;
}
- 时间复杂度 --- 遍历了整个数组,其中n为数组的长度
- 空间复杂度 --- 辅助数组的大小n,其中n为数组的长度
总结
- 仅考虑时间复杂度的题目,一般都用时间换空间的解法,其中使用辅助数组的方式最是常见。