Day17 算法题-23题:找出未出现的最小正整数

94 阅读2分钟

题目描述:

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

1)给出算法的基本设计思想。

2)根据设计思想,采用 C 或 C++ 语言描述算法关键之处给出注释。

3)说明你所设计算法的时间复杂度和空间复杂度。

1)思路:

为追求时间上尽可能高效,则申请一个辅助数组 大小和给定数长相等初始化为0,用来标记所出现的过的正整数,对应位置设为1。如若给定数中出现了小于0或者大于长度n的值,那么数组中一定会出现空缺位置,即未出现的最小正整数一定在辅助数组里;如若所有元素都为正整数且小于等于n,那么最小正整数就是n+1。

2)具体实现:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//2018 统考真题
//题目:找出数组中未出现的最小正整数
typedef int ElemType;
typedef struct{
    ElemType *data;
    int TableLen;
}SqList;    //动态分配

void InitList (SqList &L,int len)//初始化顺序表
{
    L.TableLen = len;
    L.data = (ElemType*)malloc(sizeof(ElemType)*L.TableLen);
    int i;
    srand(time(NULL));  //随机取值
    for (i = 0;i < L.TableLen ; i++)
    {
        L.data[i] = rand()%10;
    }
}

void print_list(SqList L)//打印函数
{
    for(int i = 0; i<L.TableLen ;i++)
    {
        printf("%-3d",L.data[i]);
    }
    printf("\n");
}

ElemType NotFindInt(SqList L,int n)
{
    ElemType *B;        //标记数组用来标记已有元素
    B = (ElemType*)calloc(n+1,sizeof(ElemType));
    int i;
    for (i = 0;i < n;i++)
    {
        if(L.data[i] > 0 && L.data[i]<=n)//只标记小于数组长度的正整数
            B[L.data[i]] = 1;//遍历数组用标记数组的下标记录出现的元素
    }
    i=1;
    while(B[i]!=0)  i++;
    return i;       //返回数组下标
}

int main() {
    SqList L;
    InitList(L,5);
    print_list(L);
    ElemType e;
    e = NotFindInt(L,5);
    printf("%d",e); //打印未出现的最小正整数
    return 0;
}

3)复杂度:

因为只对两数组分别进行了一次遍历,则时间复杂度为 O(n); 而申请了一个大小为n的辅助数组,故空间复杂度为O(n)

运行结果:

屏幕截图 2023-03-17 181847.png

ps:为了省事我从数组下标为1开始,申请了n+1的大小