【数据结构每日一题】线性表——未出现的最小正整数

文章介绍了如何使用空间换时间的策略解决数据结构线性表习题,通过构建辅助数组,查找数组中未出现的最小正整数。算法首先遍历数组标记正整数,然后遍历辅助数组找到第一个未被占用的正整数位置,返回该位置作为结果。当所有正整数都出现时,结果为n+1。
摘要由CSDN通过智能技术生成

[数据结构习题]线性表——未出现的最小正整数



👉知识点导航💎:【数据结构】线性表——顺序存储

👉[王道数据结构]习题导航💎: p a g e 19.13 page19.13 page19.13

本节为线性表的习题

在这里插入图片描述




题目描述:
在这里插入图片描述



🎇思路:补空法

🔱思路分析:

我们先对题目进行分析,题目要求得到一个在时间上尽可能高效的算法找到数组中未出现的最小正整数,于是,我们采取空间换时间的策略,之前我们做过的题都是尽可能将空间复杂度压缩为常数级,而这里选择让出空间,我们则可以构造一个辅助数组b[n]


我们手算的想法是:从1开始不断增大,一一检查,最先发现没在数组中的元素就是最小正整数
在这里插入图片描述

所以,我们可以得到:

对于小于等于0的数可以直接排除,对于大于0的数,我们一一检查从1开始的正整数,判断是否在数组中出现


算法思路:这就是为什么要构造辅助数组的原因,我们换一种思路,把一一检查数组中是否存在该正整数换成遍历数组,每遇到一个正整数就将它放入辅助数组对应的空中,最后遍历辅助数组,最先遇到的空即为最小正整数


😍 我们再来看一个重要性质:

最小正整数一定在 [ 1 , n + 1 ] [1,n+1] [1,n+1]之间

🍰def:

  1. 最特殊的情况就是 [ 1 , n ] [1,n] [1,n]之间没有空缺,原数组的元素含有 [ 1 , n ] [1,n] [1,n]的所有数,这时候遍历辅助数组时,发现 [ 1 , n ] [1,n] [1,n]之间的数 都被填满了,无法插入 [ 1 , n ] [1,n] [1,n]之间的空,因此,最后落到 1 + n 1+n 1+n
    最小正整数 x = n + 1 x=n+1 x=n+1

在这里插入图片描述


  1. 一般的情况就是 [ 1 , n ] [1,n] [1,n]之间的数存在空缺
    最小正整数 x ∈ [ 1 , n ] x∈[1,n] x[1,n]

🎁综上所述,最小正整数一定是落在 [ 1 , n ] [1,n] [1,n]上的,因此,我们构造辅助数组长度为n,也就是存放正整数 [ 1 , n ] [1,n] [1,n],所以<=0 / >n 的数都可以舍去


🍰algorithm step:

  1. 分配一个内存空间存放 b [ n + 1 ] b[n+1] b[n+1](让下标与值对齐),用来记录a中是否出现了1~n的正整数
  2. 第一次遍历:
    遍历数组a, 1 < = a [ i ] < = n 1<=a[i]<=n 1<=a[i]<=n,将辅助数组该下标处标记为1,表示被占有;
    否则直接跳过,此时必然导致 [ 1 , n ] [1,n] [1n]之间存在空位
  3. 第二次遍历:
    遍历数组b(从1开始),第一个出现值为0的位置即为所求的最小正整数

    若遍历结束都没有出现0,则表明结果为 n + 1 n+1 n+1


功能函数实现:

🎁这里补充一下memset的用法:
memset的作用就是将某一块内存中的内容全部设置为指定的值,用来初始化新申请的内存,返回对象是一个指向存储区s的指针,从地址s开始,字节长度为n的内存全部赋值为ch

memset(void *s, int ch, size_t n);

参数列表:

  • s:指针或者数组,指向要填充的内存块赋值,从地址s开始
  • ch:初始化所赋的值
  • n:字节长度

//主函数
int FindMissmin(int a[], int n)
{
	//1.开辟一个新数组
	int *b; //定义一个指向数组的指针
	b = (int*)malloc(sizeof(int) * (n+1)); //定义一个长度为n的数组,记录元素1-n
	if (b == NULL)
	{
		cout << "内存分配失败" << endl;
		return 0;
	}
	memset(b, 0, sizeof(int) * (n + 1)); //作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作
		//简单来说,就是将某一块内存的全部内容设置为指定的值

	//2.填空
	for (int i = 0; i < n; i++) {
		if (a[i] > 0 && a[i]<=n) //将范围锁死在1到n之间
			*(b+a[i])=1; //表示该位置被占用了
			//这里用vs写的时候 若为b[a[i]]=1 会报错,写入"b"时缓冲区溢出,还不知道为什么...
	}

	//3.插空
	int res;
	for (res=1; res <= n; res++) {
		if (b[res] == 0) //有空就插
			break;
	}
	return res;
}

完整代码实现:

#include<iostream>
#include <stdlib.h>
#define Maxsize 50
using namespace std;

//主函数
int FindMissmin(int a[], int n)
{
	//1.开辟一个新数组
	int *b; //定义一个指向数组的指针
	b = (int*)malloc(sizeof(int) * (n+1)); //定义一个长度为n的数组,记录元素1-n
	if (b == NULL)
	{
		cout << "内存分配失败" << endl;
		return 0;
	}
	memset(b, 0, sizeof(int) * (n + 1)); //作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作
		//简单来说,就是将某一块内存的全部内容设置为指定的值

	//2.填空
	for (int i = 0; i < n; i++) {
		if (a[i] > 0 && a[i]<=n) //将范围锁死在1到n之间
			*(b+a[i])=1; //表示该位置被占用了
			//这里用vs写的时候 若为b[a[i]]=1 会报错,写入"b"时缓冲区溢出,还不知道为什么...
	}

	//3.插空
	int res;
	for (res=1; res <= n; res++) {
		if (b[res] == 0) //有空就插
			break;
	}
	return res;
}


void InitList(int* a)
{
	int x,i=0;
	while (cin >> x) {
		a[i++] = x;
		if (cin.get() == '\n')
			break;
	}
}

int main() {
	//int a[Maxsize];
	int a[Maxsize];
	int len;
	cout << "请输入数组长度:" << endl;
	cin >> len;
	cout << "请输入数组:" << endl;
	InitList(a);

	cout << "未出现的最小正整数为:" << FindMissmin(a, len) << endl;

	system("pause");
	return 0;
}

输出结果:

在这里插入图片描述



🎇这是一道关于线性表的操作的真题~🎇

如有错误,欢迎指正~!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DAY Ⅰ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值