一 概述
在保存整数的顺序表L中查找未出现的最小正整数,如,顺序表[-5 3 2 3]中未出现的最小正整数为1,顺序表[1 2 3 4]中未出现的最小正整数为5。
二 算法思想
题外话:在早些时候,存储技术没有这么发达,所以在计算机某些实现方面采用的是时间换空间,随着存储技术的发展,现在时间对于很多领域来说,比空间更加重要,所以,现在大多情况下是采用空间换时间的方法。
我们分配一个用于标记的数组Sign[L.length],用以记录L中是否出现了1~L.length中的正整数,Sign[0]对应正整数1,而Sign[n-1]对应正整数L.length,初始化时Sign中的值全为0。由于L中包含L.length个整数,因此可能返回的值是1~L.length+1,当A中n个数恰好为1~L.length是,直接返回未出现的最小正整数是L.length+1。当线性表L中出现了小于等于0或者大于L.length的值是,就会导致1~L.length中出现空余位置。则未出现的最小正整数必然在1~L.length中,因此对于L中出现了小于等于0或大于L.length的值可以不采取任何操作。
算法流程:从L.elem[0]开始遍历顺序表L,若0<L[i]<=L.length,则令Sign[L[i]-1] =3,其实可以定义为一个任何不为零的数以区别Sign[i]中初始化为0的情况,否则不做任何操作;对于遍历完L之后,开始遍历标记数组Sign[],若能够查找到第一个满足Sign[i]==0的下标i,返回i+1,即为未出现的最小正整数,此时说明L中未出现的最小正整数在1~L.length之间。若Sign[i]中的数据全部不为0,返回i+1,此时的i=L.length,i+1即为L.length+1,说明L中未出现的最小正整数是n+1。
三 算法实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int Status;
typedef int ElemType;
#define MAXSIZE 100
#define ERROR -1
#define OK 0
typedef struct {
ElemType *elem;
int length;
}SqList;
Status init_Queue(SqList &L){
L.elem = new ElemType[MAXSIZE]; //初始化最大长度的顺序表
if(!L.elem){
return ERROR; //初始化失败
}
L.length = 0; //初始时数据表为空
return OK;
}
int findMissMinInt(SqList &L) {
int i, *Sign; //标记数组*Sign是一个指针类型,此处Sign中是数组的地址
/*如:*a = b;
此时:a中保存的是变量b的内存地址;
*a则是取变量b的值。
&b就是取变量b的地址。
*/
Sign = (int *)malloc(sizeof(int)*L.length); //C语言分配数组空间
//memset(Sign,0,sizeof(int)*L.length);
memset(Sign,0,sizeof(Sign)); //将标记数组元素全部赋值为0
for(i = 0; i < L.length;i++) {
if(L.elem[i] > 0 && L.elem[i] <= L.length){
Sign[L.elem[i] - 1] = 3;
}
}
for(i = 0; i < L.length;i++) {
if(Sign[i] == 0) {
break;
}
}
return i+1;
}
int main(){
SqList L;
printf("1.初始化顺序表!\n");
printf("2.输入8个不同的数字!\n");
printf("3.顺序表L中未出现的最小正整数!\n");
printf("0.退出!\n");
int elect = -1,length;
while(elect !=0){
printf("请选择你的后续操作:");
scanf("%d",&elect);
switch(elect){
case 1:
if(!init_Queue(L)){
printf("初始化顺序表成功!\n");
}else{
printf("初始化顺序表失败!\n");
}
break;
case 2:
printf("请初始化顺序表的长度:");
scanf("%d",&length);
printf("请输入%d个整数:",length);
for(int i = 0; i < length; i++){
scanf("%d",&L.elem[i]);
L.length = length;
}
break;
case 3:
printf("顺序表L中未出现的最小正整数为:%d\n",findMissMinInt(L));
break;
}
}
return OK;
}
算法结果,当Sing[]中存在0值:
算法结果,当Sign[]中不存在0值:
四 算法的时间复杂度和空间复杂度分析
算法时间复杂度:按顺序查找的时间复杂度分析,该算法的时间复杂度为O(n)。
算法空间复杂度:在算法实现过程中,使用标记数组Sign[n]作为辅助空间,故该算法的空间复杂度为O(n)。