题目来源: 计算机考研408真题2018年41题
题目描述:
-
描述: 41.(13分)给定一个含n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数,例如,数组{-5,3,2,3}中未出现的最小正整数是1:数组{1,2,3}中未出现的最小正整数是4。 要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C、C++或Java语言描述算法,关键之处给出注释.
3)说明你所设计算法的时间复杂度和空间复杂度。 -
示例:
输入:-5,3,2,3
输出:1
输入:1,2,3
输出:4
思路:空间换时间
- 分配一个用于标记的数组B[n],用于记录数组arr中是否出现了1~n中的正整数,B[0]对应正整数1,B[n-1]对应正整数n,初始化B中全部为0
- 由于A中含有n个整数,因此可能返回的值是1
n+1,当A中n个数恰好为1n时返回n+1.- 当数组A中出现了小于等于0或大于n的值时,会导致B中记录的1
n中出现空余位置,返回结果必然在1n中,即所求的缺少的最小正整数必然在1~n中 - 因此对于A中出现了小于等于0或大于n的值可以不采取任何操作
- 当数组A中出现了小于等于0或大于n的值时,会导致B中记录的1
具体实现:
#include <iostream>
#include <cstring>
using namespace std;
int findMissin(int arr[], int n) {
int i, *B;
B = (int *) malloc(sizeof(int) * n);
memset(B, 0, sizeof(int) * n); //将数组B全部初始化为0
for (i = 0; i < n; i++)
if (arr[i] > 0 && arr[i] <= n) //仅仅对数组arr中在(0,n]范围内的数据进行操作
B[arr[i] - 1] = 1; //将其放入数组B中
for (i = 0; i < n; i++) { //对数组B进行遍历,检查是否有存储元素为0
if (B[i] == 0)
break; //如果有存储元素为0,那么便找到了最小的正整数
}
return i + 1; //如果上面对数组B的遍历后,数组B所有的元素都为1,
//说明最小正整数是n+1
}
int main() {
int arr[] = {-5,2,3};
int res = findMissin(arr, 3);
cout<<res; //输出结果为1
}
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情”