顺序表中的最小正整数问题

一 概述

在保存整数的顺序表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)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章