【2018年数据结构真题】

方法一

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

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

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

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

读完题目先找关键词,这里可以直接提取这样几个关键词

  • 使用数组,求未出现的最小正整数
  • 看到数组,是不是想到是否有序
  • 时间+空间尽可能高效

暴力解:快速排序,然后扫描一遍数组

先对数组A快速排序得到升序序列,然后遍历数组找到第一个未出现的最小正整数。

void Qsort(int A[], L, R){      //a数组保存数据,L和R是边界if (L>=R) return;      //当前区间元素个数<=1则退出int key, i=L, j=R;     //i和j是左右两个数组下标移动//把a数组中随机一个元素和A[L]交换,快排优化,使得基准值的选取随机key=A[L]; //key作为枢值参与比较while (i<j){while (i<j && A[j]>key) j--;while (i<j && A[i]<=key) i++;if (i<j) swap(A[i], A[j]); //交换A[i]和A[j]}swap(A[L], A[i]);Qsort(A, L, i-1); //递归处理左区间Qsort(A, i+1, R); //递归处理右区间}void ans(int A[], n){ //算法代码Qsort(A, 0, n-1);int i=0;while (i<n && A[i]<=0) i++;if (i==n){ //数组A全是非正数cout<<1;//输出1 return;}/*到这里,A[i]是数组中最小的正数*/ int t=1;//t从1开始for (int j=i; j<n; j++){ if (t==A[j])continue; if (t+1==A[j])t++;else{ //t+1空缺cout<<t+1; //输出j-i+1 return;}cout<<t+1;//遍历完数组,输出t+1}
}

方法二

解析:

思想借鉴到了 Counting sort 中的方法。既然不能用额外空间,那就只有利用
数组本身,跟 Counting sort 一样,利用数组的 index 来作为数字本身的索引,把正
数按照递增顺序依次放到数组中。即让 A[0]=1, A[1]=2, A[2]=3, … , 这样一来,
最后如果哪个数组元素违反了 A[i]=i+1 即说明 i+1 就是我们要求的第一个缺失的正
数。对于那些不在范围内的数字,我们可以直接跳过,比如说负数,0,或者超过数组
长度的正数,这些都不会是我们的答案。

思路:

交换数组元素,使得数组中第 i 位存放数值(i+1)。最后遍历数组,寻找第一
个不符合此要求的元素,返回其下标。整个过程需要遍历两次数组,复杂度为 O(n)。
下图以题目中给出的第二个例子为例,讲解操作过程。

image.png

public int firstMissingPositive(int []A){if(A==null||A.length==0){return 1;}for(int i=0;i<A.length;i++){if(A[i]<=A.length && A[i]>0 && A[A[i]-1]!=A[i]){int temp = A[A[i]-1];A[A[i]-1] = A[i];A[i] = temp;i--;}}for(int i=0;i<A.length;i++){it(A[i]!=i+1)return i+1;}return A.length+1;
}

实现中还需要注意一个细节,就是如果当前的数字所对应的下标已经是对应数字了,
那么我们也需要跳过,因为那个位置的数字已经满足要求了,否则会出现一直来回交
换的死循环。这样一来我们只需要扫描数组两遍,时间复杂度是 O(2*n)=O(n),而且
利用数组本身空间,只需要一个额外变量,所以空间复杂度是 O(1)。

补充

Counting sort 基本思想

对于给定的输入序列中的每一个元素 x,确定该序列中值小于 x 的元素的个数 。一
旦有了这个信息,就可以将 x 直接存放到最终的输出序列的正确位置上。它创建一个
长度为这个数据范围的数组 C,C 中每个元素记录要排序数组中对应记录的出现个
数。

下面以示例来说明这个算法:

假设要排序的数组为 A = {1,0,3,1,0,1,1}这里最大值为 3,最小值为 0,那么我们
创建一个数组 C,长度为 4。

然后一趟扫描数组 A,得到 A 中各个元素的总数,并保持到数组 C 的对应单元中。比如 0 的出现次数为 2 次,则 C[0] = 2;1 的出现次数为4 次,则 C[1] = 4。由于 C 是以 A 的元素为下标的,所以这样一做,A 中的元素在 C中自然就成为有序的了,这里我们可以知道 顺序为 0,1,3 (2 的计数为 0)然后我们把这个在 C 中的记录按每个元素的计数展开到输出数组 B 中,排序就完成了。

也就是 B[0] 到 B[1] 为 0 B[2] 到 B[5] 为 1 这样依此类推。
这种排序算法,依靠一个辅助数组来实现,不基于比较,算法复杂度为 O(n) ,但由
于要一个辅助数组 C,所以空间复杂度要大一些,由于计算机的内存有限,所以这种
算法不适合范围很大的数的排序。

上述为计数排序算法的经典解法,不过这个解法并不是最优的,因为空间复杂度还应
该可以优化,我们完全可以不要那个输出的数组 B,直接对 C 进行排序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/206940.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Vue的体检预约管理系统

基于SpringBootVue的体检预约管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 管理员界面 用户界面 摘要 体检预约管理系统是一种基于Spring Boot…

【React-Router】路由快速上手

1. 创建路由开发环境 # 使用CRA创建项目 npm create-react-app react-router-pro# 安装最新的ReactRouter包 npm i react-router-dom2. 快速开始 // index.jsimport React from react; import ReactDOM from react-dom/client; import ./index.css; import App from ./App; i…

JSP EL表达式基本使用

今天我们来说EL表达式 这在整个jsp中都是非常重要的一章 因为 如果我们用 <%属性%> 属性为空时 直接就是个 null 这个肯定是不能让用户看到的东西 所以 我们就需要EL表达式 例如 我们jsp代码编写如下 <% page contentType"text/html; charsetUTF-8" page…

专访|OpenTiny 开源社区 常浩:完成比完美更重要

前言 2023年已过大半&#xff0c;备受关注的 OpenTiny*开源之夏活动也顺利结项。开源之夏由中国科学院软件研究所发起的计划&#xff0c;目的在于鼓励在校学生积极参与开源软件的开发维护&#xff0c;推动优秀开源软件社区的繁荣发展。该活动联合各大开源社区&#xff0c;聚焦…

python实现调和反距离空间插值法AIDW

1 简介 AIDW 主要是针对 IDW 的缺点进行了改进&#xff0c;考虑了样本点与预测点的位置&#xff0c;即方向和距离&#xff0c;具体见下图&#xff1a; 2 改进 IDW 公式&#xff1a; 从IDW算法可看出&#xff0c;插值点的估算值仅与插值样本距插值点的远近相关&#xff0c;并未…

99. 恢复二叉搜索树

99. 恢复二叉搜索树 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 99. 恢复二叉搜索树 https://leetcode.cn/problems/recover-binary-search-tree/description/ 完成情况&#xff1a; 解题思路&a…

接口自动化测试实战经验分享,测试用例也能自动生成

作为测试&#xff0c;你可能会对以下场景感到似曾相识&#xff1a;开发改好的 BUG 反复横跳&#xff1b;版本兼容逻辑多&#xff0c;修复一个 BUG 触发了更多 BUG&#xff1b;上线时系统监控毫无异常&#xff0c;过段时间用户投诉某个页面无数据&#xff1b;改动祖传代码时如履…

HCIA-Datacom跟官方路线学习

通过两次更换策略。最后找到最终的学习方案&#xff0c;华为ICT官网有对这个路线的学习&#xff0c;hcia基础有这个学习路线&#xff0c;hcip也有目录路线。所以&#xff0c;最后制定学习路线&#xff0c;是根据这个认证的路线进行学习了&#xff1a; 官网课程&#xff1a;课程…

rsync配置和守护进程实践

目录 一、rsync概念 1.rsync简介 2.rsync特点 3、增量和全局传输 二、Rsync工作方式 1.准备好rsync备份服务器 2.本地的数据传输模式 3.远程的数据传输模式 4.rsync数据推拉模式 三、实践 1.准备三台虚拟机 2.都安装rsync服务 3.拉取远程文件 3.推送文件 4.rsyn…

机器学习实战第1天:鸢尾花分类任务

专栏介绍 欢迎订阅专栏——机器学习实战 机器学习实战_Nowl的博客-CSDN博客 纸上得来终觉浅 本专栏项目将着重于解决各类实际机器学习问题&#xff0c;带你上手各种场景的实际问题 数据集可以在我的资源中找到&#xff0c;也可以自行搜索 文中导入数据集的路径要改成自己的…

Vue2系列 — 渲染函数 (render + createElement)

官网文档&#xff1a;https://v2.cn.vuejs.org/v2/guide/render-function.html 1 render 函数 render 函数 不使用模板&#xff0c;使用 js 生成虚拟 dom 2 createElement() 接受的参数&#xff1a; 参数1 节点类型参数2 attribute参数3 子节点 3 DEMO <template>&…

采用connector-c++ 8.0操作数据库

1.下载最新的Connector https://dev.mysql.com/downloads/connector/cpp/&#xff0c;下载带debug的库。 解压缩到本地&#xff0c;本次使用的是带debug模式的connector库&#xff1a; 注&#xff1a;其中mysqlcppconn与mysqlcppconn8的区别是&#xff1a; 2.在cmakelist…