数据结构练习-线性表的顺序存储

----------------------------------------------------------------------------------------------------------------------------- 

        1. 具有n个元素的线性表采用顺序存储结构,在其第i个位置插入一个新元素的算法间复杂度为

(     )(1≤i≤n+1) 。                                              

        A.O(1)                                        B.O(i)

        C.O(n)                                         D.O(n²)

        解析:  

        线性表的顺序存储结构

        线性表的顺序存储结构意味着表中的元素是在连续的存储单元里存放的,类似于数组。每个元素都可以通过起始地址加上偏移量直接访问。因此,访问任何一个位置的元素的时间复杂度是O(1),即常数时间复杂度。

        插入操作

        当我们在顺序存储的线性表中的第i个位置插入一个新元素时,需要进行以下步骤:

  1. 检查有效性:首先确认插入位置i是否有效,即检查1≤i≤n+1(n为线性表当前的元素数量)。
  2. 腾出位置:从最后一个元素开始,将从第i个位置开始的所有元素向后移动一个位置,以腾出位置i。
  3. 插入元素:将新元素放入第i个位置。
  4. 调整表的大小:线性表的元素数量n增加1。

        算法的时间复杂度

        时间复杂度是衡量算法执行时间随输入数据规模增长而增长的速度或者增长顺序的一种度量。在本题中,我们关心的是插入操作的时间复杂度:

  • 插入操作的关键在于移动元素。假设要在第i个位置插入新元素,需要移动从位置i到位置n的所有元素(即n-i+1个元素)。每次移动操作可以视为常数时间操作,但总的操作次数与i的位置有关。最坏的情况是i=1,此时需要移动所有n个元素。
  • 因此,插入操作的时间复杂度依赖于i的值,具体来说,是O(n)——随着线性表长度n的增长,最坏情况下的时间开销线性增加。

        选项分析

  • A. O(1):这表示插入操作的时间复杂度是常数,这显然不适用于我们需要移动多个元素的情况。
  • B. O(i):虽然移动的元素数量与i有关,但时间复杂度应表示为与线性表总长度n相关的最坏情况,而不是i。
  • C. O(n):这是正确的选项,因为最坏的情况下我们需要移动n个元素,时间复杂度是线性的。
  • D. O(n²):这表示时间复杂度是n的平方,通常用于双层循环等情况,与本题情景不符。

        因此,正确答案是 C. O(n)。这代表在顺序存储结构的线性表中进行插入操作时,最坏情况下的时间复杂度是线性的,与表中元素的数量成线性关系。

        笔记:

  1. 顺序存储结构:线性表的元素在内存中连续存放,类似数组。
  2. 插入操作
    • 位置i:在第i个位置插入新元素(1≤i≤n+1)。
    • 步骤:将第i个位置及之后的元素向后移动,腾出空间插入新元素。
  3. 时间复杂度:O(n)
    • 原因:最坏情况下(i=1),需要移动整个表的所有元素。
    • 解释:时间复杂度与线性表的长度n线性相关。

----------------------------------------------------------------------------------------------------------------------------- 

        2. 线性表采用顺序存储结构时,其元素地址(  )。                

        A.必须是连续的

        B.部分地址必须是连续的

        C. 一定是不连续的

        D. 连续不连续都可以

        解析:

        元素的地址计算

        在顺序存储结构中,元素的存储地址可以通过下面的公式计算: 地址(�[�])=基地址+�×元素大小地址(A[i])=基地址+i×元素大小 其中,�[�]A[i] 表示数组中的第 �i 个元素,基地址是数组第一个元素的存储地址,元素大小是存储每个元素所需的字节数。这个公式表明,每个元素的存储位置仅依赖于它的索引,这保证了元素之间物理地址上的连续性。

        现在,让我们来逐一看看每个选项的意义和是否符合顺序存储结构的特点:

  • A. 必须是连续的 这个选项正确。在顺序存储结构中,所有元素都是连续存放的,这是顺序存储的定义和特点。每个元素的地址直接依赖于其前一个元素的地址和元素本身的大小。

  • B. 部分地址必须是连续的 这个选项不正确。顺序存储不仅是部分连续,而是完全连续。所有元素的地址从头到尾都是连续的,没有间断。

  • C. 一定是不连续的 这个选项完全错误。顺序存储结构的一个基本特征就是地址连续性,选项C与顺序存储的定义相矛盾。

  • D. 连续不连续都可以 这个选项也不正确。在顺序存储结构中,元素地址的连续性是必须的,不可能是不连续的。

        正确答案是 A. 必须是连续的。这反映了顺序存储结构的核心特性,即在物理内存中元素之间的连续性。这种存储方式使得访问速度快,因为可以直接通过计算偏移来定位任何元素,但这也意味着插入和删除操作可能会需要移动多个元素以保持这种连续性。理解这一点对于初学者来说是基础且重要的。

        笔记:

  1. 顺序存储结构:类似数组,线性表中的元素在内存中连续存放。
  2. 地址连续性:在顺序存储结构中,每个元素的地址都是连续的。
  3. 地址计算公式:地址(A[i])=基地址+i×元素大小,显示了如何根据第一个元素的位置和元素索引计算任何元素的地址。

----------------------------------------------------------------------------------------------------------------------------- 

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

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

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

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

        解析:

        真题的的解析看不明白,自己的版本,至少能实现。。

        (1)

  1. 顺序搜索:从1开始,逐个检查每个正整数是否存在于数组中。这种顺序搜索方法保证了第一个未在数组中找到的正整数即是我们要找的答案。

  2. 全数组遍历:对于每一个正整数x,遍历整个数组,检查x是否作为元素存在。如果存在,则增加x的值继续检查下一个整数;如果不存在,立即返回该数作为未出现的最小正整数。

  3. 停止条件:这种方法没有事先设定的停止条件,它会继续增加x的值,直到找到一个不在数组中的正整数为止。

        (2)

#include <bits/stdc++.h>  //万能库using namespace std; // 使用 std 命名空间// 定义一个函数,用于找出数组中未出现的最小正整数
int findMissingPositive(int nums[], int size) {int x = 1; // 初始化x为1,从1开始寻找未出现的最小正整数while (true) { // 开始一个无限循环bool found = false; // 初始化found为false,用于标记x是否在数组中找到for (int i = 0; i < size; ++i) { // 遍历数组if (nums[i] == x) { // 如果数组中的某个元素等于xfound = true; // 设置found为truebreak; // 退出循环}}if (!found) { // 循环结束后,如果没有找到xreturn x; // 返回x作为未出现的最小正整数}x++; // 如果x在数组中被找到,x加1,检查下一个数字}
}// 主函数
int main() {int nums[] = {1, -5, 3, 2, 3}; // 定义一个数组int size = sizeof(nums) / sizeof(nums[0]); // 计算数组的大小cout << "未出现的最小正整数是: " << findMissingPositive(nums, size) << endl; // 输出结果int nums2[] = {1, 2, 3}; // 定义第二个数组int size2 = sizeof(nums2) / sizeof(nums2[0]); // 计算第二个数组的大小cout << "未出现的最小正整数是: " << findMissingPositive(nums2, size2) << endl; // 输出第二个结果return 0; // 主函数返回0,程序结束
}
  • 使用了C++内置的静态数组。
  • 数组的大小通过sizeof(nums) / sizeof(nums[0])获得。
  • 使用了一个基本的循环和线性搜索检查数组中是否存在某个数。

        (3)

  • 时间复杂度: 与前面相同,为O(n*m),其中n是数组的大小,m是未出现的最小正整数。每次增加x都要遍历整个数组检查是否存在。
  • 空间复杂度: 为O(1),除了输入的数组外,只使用了固定的额外空间。

----------------------------------------------------------------------------------------------------------------------------- 

        4.

        解析:

        题目不讲人话,其实就是,在一个数组中找出一个数,这个数的出现次数超过数组长度的一半。

        (1)

1. 双重遍历(暴力法)

  • 逐个检查:算法通过外层循环逐个选取数组中的每一个元素。
  • 计数匹配:内层循环再次遍历整个数组,计数当前选中元素的出现次数。

2. 检查条件满足

  • 超过半数判定:每次内层循环结束后,检查当前元素的出现次数是否超过数组长度的一半。
  • 立即返回:如果发现某个元素的出现次数满足超过半数的条件,则立即返回该元素作为主元素。

3. 无主元素处理

  • 结束遍历:如果外层循环结束后,没有任何一个元素的出现次数超过数组长度的一半,则返回 -1,表示数组中不存在主元素。

        (2)

#include <iostream> // 包含标准输入输出流库,用于输入输出操作using namespace std; // 使用标准命名空间,简化类型名称// 定义一个函数,用于找出数组中的主元素
int findMajorityElement(int nums[], int size) {// 外层循环遍历数组中的每个元素for (int i = 0; i < size; ++i) {int count = 0; // 初始化计数器,用于统计当前元素的出现次数// 内层循环再次遍历数组,用于计数当前外层元素的出现次数for (int j = 0; j < size; ++j) {if (nums[j] == nums[i]) { // 如果内外循环的元素相同++count;  // 增加计数器}}// 检查当前元素的出现次数是否超过数组长度的一半if (count > size / 2) {return nums[i];  // 如果是,返回当前元素作为主元素}}return -1;  // 如果循环结束没有找到任何主元素,返回-1
}// 主函数,程序入口点
int main() {// 初始化第一个数组和计算其大小int nums[] = {0, 5, 5, 3, 5, 7, 5, 5};int size = sizeof(nums) / sizeof(nums[0]);  // 计算数组大小,即元素数量// 输出第一个数组的主元素结果cout << "主元素是: " << findMajorityElement(nums, size) << endl;// 初始化第二个数组和计算其大小int nums2[] = {0, 5, 5, 3, 5, 1, 5, 7};int size2 = sizeof(nums2) / sizeof(nums2[0]); // 计算第二个数组的大小// 输出第二个数组的主元素结果cout << "主元素是: " << findMajorityElement(nums2, size2) << endl;return 0; // 程序正常结束
}
  • 数组初始化和大小计算: 使用 sizeof 方法来计算数组的元素数量。
  • 嵌套循环: 外层循环遍历数组的每个元素,内层循环遍历整个数组来计数当前元素的出现次数。
  • 主元素的检查: 如果一个元素的出现次数超过了数组长度的一半,则它是主元素。

        (3)

  • 时间复杂度: O(n^2),其中 n 是数组的长度。对每个元素,我们需要再次遍历整个数组来计算其出现的次数。
  • 空间复杂度: O(1),因为我们没有使用除输入数组和少数几个变量外的任何额外空间。

----------------------------------------------------------------------------------------------------------------------------- 

        5.

        解析:

        (1)

        算法的基本思想是先将两个升序数组合并成一个大的升序数组,然后直接从中取出中位数。合并后的数组长度为两个输入数组长度之和,合并过程中保持数组的排序特性。

        (2)

#include <iostream>
#include <algorithm>using namespace std;// 合并两个升序数组并找到中位数的函数
int findMedianSortedArrays(int A[], int B[], int size) {int *C = new int[2 * size];  // 动态分配合并后数组的空间// 合并两个数组int i = 0, j = 0, k = 0;while (i < size && j < size) {if (A[i] < B[j]) {C[k++] = A[i++];} else {C[k++] = B[j++];}}// 如果还有剩余,继续添加while (i < size) {C[k++] = A[i++];}while (j < size) {C[k++] = B[j++];}// 计算中位数int midIndex = (2 * size) / 2;int median = C[midIndex];delete[] C;  // 释放动态分配的内存return median;
}int main() {int A[] = {11, 13, 15, 17, 19};int B[] = {2, 4, 6, 8, 20};int size = sizeof(A) / sizeof(A[0]);cout << "中位数是: " << findMedianSortedArrays(A, B, size) << endl;return 0;
}

        (3)

  • 时间复杂度: 合并两个数组的过程是线性的,即O(n),因为每个元素都正好被访问一次。这是因为两个数组都已经排序。
  • 空间复杂度: 额外使用了一个大小为 2n 的数组来存储合并后的结果,因此空间复杂度是 O(n)。

----------------------------------------------------------------------------------------------------------------------------- 

        6.

        解析:

      “左移两个位置”意味着最开始的两个数字被移到了列表的末尾,而其他数字都向前移动了两个位置。

        (1)

        具体来说,我们可以创建一个新的数组,将原数组从指定位置开始的元素复制到新数组的开头,然后再把原数组开头到指定位置的元素复制到新数组的后面。

        (2)

#include <iostream>using namespace std;void rotate(int arr[], int n, int p) {int* temp = new int[n]; // 动态分配一个临时数组// 将原数组的 p 到 n-1 位置的元素复制到新数组的开头for (int i = p; i < n; i++) {temp[i - p] = arr[i];}// 将原数组的 0 到 p-1 位置的元素复制到新数组的后面for (int i = 0; i < p; i++) {temp[n - p + i] = arr[i];}// 将新数组的值复制回原数组for (int i = 0; i < n; i++) {arr[i] = temp[i];}delete[] temp; // 释放临时数组内存
}int main() {int arr[] = {1, 2, 3, 4, 5}; // 示例数组int n = sizeof(arr) / sizeof(arr[0]); // 计算数组大小int p = 2; // 左移的位置数rotate(arr, n, p);// 输出移动后的数组for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;return 0;
}

        (3)

        时间复杂度: O(n)。这是因为算法中涉及到三次遍历整个数组的操作:一次是填充临时数组,一次是复制临时数组回原数组。

        空间复杂度: O(n)。算法使用了一个与原数组同样大小的临时数组来辅助移动数据。

----------------------------------------------------------------------------------------------------------------------------- 

        补充声明,由于笔者为初学者,故,算法类练习全部采用了暴力解法,而实际情况下暴力只要正确,也能拿到8/11的分数。其中某题的明确评分法子。

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

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

相关文章

干货:一篇文章让你掌握用户运营 沈阳新媒体运营培训

用户对于产品的重要性不言而喻&#xff0c;而用户运营作为最接近用户的一环&#xff0c;自然而然受到了各大互联网公司的重视。想要掌握用户运营&#xff0c;必须得先知道其市场需求和主要技能&#xff0c;本文从这两个方面对用户运营展开了分析拆解&#xff0c;梳理用户运营的…

实现printf功能代码效果

1、使用 vsnprintf 模拟 printf 功能 非宏定义情境下&#xff0c;可以用作开启通讯口调试功能 实际上是通过 vsnprintf 将接收到的 format格式化后解析到缓存区&#xff0c;这里存在缓存区大小限制&#xff0c;以及代码大小区别 #include <stdarg.h> #include "std…

不墨迹,向媒体投稿不讲攻略,直接上方法

作为一名单位信息宣传员,我曾深陷于向媒体投稿的泥沼之中,饱尝了费时费力、审核严苛、出稿缓慢的苦涩,承受着领导急切期盼与自我压力交织的煎熬。然而,当我有幸接触到智慧软文发布系统,这一切困境如同阴霾散去,取而代之的是便捷流畅的投稿流程,以及领导满意、团队轻松的工作氛围…

parallels desktop 19密钥分享 附PD虚拟机安装教程 支持M/intel

PD19虚拟机安装破解教程 Parallels Desktop 百度网盘下载&#xff1a;https://pan.baidu.com/s/1ezQmJAjIx796NEr9WZbcOg 提取码: 8w61 &#xff08;地址容易失效&#xff0c;来之不易&#xff0c;务必点赞和收藏&#xff0c;如果失效了请到评论区留言反馈&#xff09; 注意&…

VPP 源码学习总结

当我们在VPP/plugins目录下注册了自己的node后&#xff0c; 肯定有一个node.func(), 那这个函数是如何执行到的呢&#xff1a; 1. 首先我们要看一下这个插件注册的时候做了什么&#xff0c; 假设node 如下&#xff1a; 编译成功后&#xff0c; 我们可以从函数vlib_plugin_earl…

Telegram mini app 登录小部件 | 自定义登录按钮 或 静默登录

先说我遇到的问题&#xff0c;我按照流程接入了 telegram 登录小部件&#xff0c;在 PC 或者 H5 可以拿到数据&#xff08;不管是选择回调函数还是回调地址的形式都可以&#xff09;&#xff0c;但是在 telegram mini app 中登录拿不到数据&#xff0c;在 telegram 中 我点击登…

RabbitMQ笔记(基础篇)

视频&#xff1a; MQ基础-01.RabbitMQ课程介绍_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1mN4y1Z7t9?p1&vd_sourced0ea58f1127eed138a4ba5421c577eb1 一、RabbitMQ简介 1.同步调用 优势&#xff1a;时效性强&#xff0c;等待结果后才返回 劣势&#xff1…

虚拟化与Docker基本概念与Docker的安装

Docker Docker 是一个开源的应用容器引擎&#xff0c;它最初是用 Go 语言开发的。Docker 允许开发者将应用程序及其依赖、库和环境打包到一个可移植的容器中&#xff0c;这个容器可以在任何支持 Docker 的 Linux 或 Windows 机器上运行&#xff0c;保证了应用在不同环境之间的…

【行为型模式】备忘录模式

一、备忘录模式概述 备忘录模式定义&#xff1a;又称之为快照模式(Snapshop Pattern)或者令牌模式(Token Pattern)&#xff0c;是指在不破坏封装的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在对象之外保存这个状态&#xff0c;这样我们就可以在需要的时候将该对…

【14-Ⅱ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

InstantMesh:利用稀疏视图大规模重建模型从单张图像高效生成3D网格

作者&#xff1a;Jiale Xu&#xff0c;Weihao Cheng&#xff0c;Yiming Gao等 编译&#xff1a;东岸因为一点人工一点智能 InstantMesh&#xff1a;利用稀疏视图大规模重建模型从单张图像高效生成3D网格在这项工作中&#xff0c;我们提出了InstantMesh&#xff0c;一个开源的…

【C语言】红黑树详解以及C语言模拟

一、红黑树的性质二、红黑树的旋转操作三、红黑树的插入操作四、红黑树的删除操作五、红黑树的应用六、C语言模拟红黑树七、总结 红黑树是一种自平衡二叉查找树&#xff0c;它能够保持树的平衡&#xff0c;从而确保查找、插入和删除的最坏情况时间复杂度为O( l o g n log_n log…

LoRA: 大模型的低秩适配

笔记整理&#xff1a;陈一林&#xff0c;东南大学硕士&#xff0c;研究方向为不确定知识图谱规则学习 链接&#xff1a;https://arxiv.org/abs/2106.09685 1、动机 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练&#xff0c;然后对特定任务或领域进行适应性…

JAVA10迭代更新

文章目录 1 概述2 语法层次的变化1_局部变量的类型推断 3 API层次的变化1_集合中新增copyOf创建只读集合2_Optional 新增了orElseThrow方法 4 其他1_垃圾回收器接口2_G1 并行 Full GC3_应用程序类数据共享(扩展 CDS 功能)4_实验性的基于 Java 的 JIT 编译器 1 概述 2018年3月21…

新能源汽车小米su7

小米su7汽车 function init() {const container document.querySelector( #container );camera new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, 1, 50000 );camera.position.set( 0, 700, 7000 );scene new THREE.Scene();scene.background ne…

vue项目中基于fabric 插件实现涂鸦画布功能

vue项目中基于fabric 插件实现涂鸦画布功能 一、效果图二、安装依赖三、main.js引入四、主要代码 一、效果图 二、安装依赖 npm install fabric 三、main.js引入 import fabric from fabric Vue.use(fabric);四、主要代码 //封装成了一个组件 <template><el-dialogt…

FlashSpeech、ID-Animator、TalkingGaussian、FlowMap、CutDiffusion

本文首发于公众号&#xff1a;机器感知 FlashSpeech、ID-Animator、TalkingGaussian、FlowMap、CutDiffusion Gradient Guidance for Diffusion Models: An Optimization Perspective Diffusion models have demonstrated empirical successes in various applications and ca…

《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制婴儿性别比例饼图

在MATLAB 中可以使用 pie 函数来创建饼图。饼图是一种展示不同部分占总体的相对比例的图表。 本示例从“婴儿出生数据.csv”文件读取婴儿出生数据&#xff0c;然后计算男性和女性婴儿的数量&#xff0c;使用MATLAB绘制饼图。 配套图书链接&#xff1a;https://item.jd.com…

AI图书推荐:AI驱动的图书写作工作流—从想法构思到变现

《AI驱动的图书写作工作流—从想法到变现》&#xff08;AI-Driven Book Creation: From Concept to Cash&#xff09;是Martynas Zaloga倾力打造的一本实用指南&#xff0c;它巧妙地将写作艺术与人工智能前沿技术相结合。此书不仅揭示了AI在图书出版领域的无限潜力&#xff0c;…

应用层协议 -- HTTPS 协议

目录 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 2、理解“加密” 二、对称加密 1、理解对称加密 2、对称加密存在的问题 三、非对称加密 1、理解非对称加密 2、中间人攻击 3、CA 证书和数字签名 四、总结 一、了解 HTTPS 协议 1、升级版的 HTTP 协议 HTTPS 也是…