[蓝蓝计算机考研算法]-day17找出数组中未出现的最小正整数

145 阅读1分钟

【2018统考真题】

给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。 例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组 {1,2,3}中未出现的最小正整数是4。

要求:

  1. 给出算法的基本设计思想。
  2. 根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
  3. 说明你所设计算法的时间复杂度和空间复杂度。

思路

定义一个数组b,并赋值为0,将数组a中出现的>0且<n+1的值在数组b中标记=1,最后循环数组b,若值等于0,则其下标为最小值。

具体步骤

  1. 输入数组,编写一个求数组中未出现的最小正整数的值的函数,并返回最小值,输出。

  2. 求最小正整数的值的函数,返回值为int类型。传入的参数为数组a和数组的大小n。

  3. 定义一个数组b(范围是1~n+1),存放数组a出现的过的值的标记。

  4. 循环数组a,判断其是否大于0且小于等于n+1,若相等则将其值在数组b中赋值为1,以做标记。

  5. 循环数组b,判断值是否为0,若是,则将下标赋值给ans并返回。注意b的下标是从1开始,1~n+1。

具体实现

#include<bits/stdc++.h>
using namespace std;

//求最小正整数的方法,传参为输入的数组和数组大小n,下标为1~n
int FindMin(int a[],int n){
	int b[n+2]={0}; //存放a[i]在范围的元素的标记值,下标为1~n+1
	int ans=1; //定义最小整数
	for(int j=1; j<n+1; j++){ //a数组只能从1开始,因为传入的数组就是从1开始的!!! 
		if(a[j]>0 && a[j]<=n+1)
			b[a[j]]=1;
	}
	for(int j=1; j<n+2; j++){
		if(b[j]==0){
			ans=j; //第一个值为0的下标即为最小值 
			break;
		}
	}
	return ans;
}

int main(){
	int a[100],i=1; //i从1开始,所以数组中的整数个数为i个
	while(cin>>a[i]){
		if(cin.get()=='\n') break; //如果换行,跳出循环,即结束输入 
		else i++; //不换行,则继续输入,i继续+1 
	}
	int ans = FindMin(a,i); //调用函数,返回最小正整数 
	cout<<ans;
	return 0;
}

时空复杂度

  • 时间复杂度:O(n)

  • 空间复杂度:O(n)

小结

注意,在用数组做参数进行传递时,如果传递之前数组下标是从1开始的,那么传入后,数组下标依然要从1开始遍历,不能从0!!!