一 概述
在保存整數的順序表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)。