数据结构学习笔记(六)链表算法题

假期结束,看点题目。

第一题

问题

设顺序表用数组A[]表示,表中元素存储在数组下标1~m+n的范围内,前m个元素递增有序,后n个元素递增有序,设计一个算法,使得整个顺序表有序。
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间复杂度和空间复杂度。

解答

(1)算法基本设计思想:
将数组A[]中的m+n个元素(假设元素为int型)看成两个顺序表,表L和表R。将数组当前状态看做起始状态,即此时表L由A[]中前m个元素构成,表R由A[]中后n个元素构成。要使A[]中m+n个元素整体有序只需将表R中的元素逐个插入表L中的合适位置即可。插入过程:取表
R中的第一个元素A[m+1]存入辅助变量temp中,让temp逐个与A[m],A[m-1],…,A[1]进行比较,当temp<A[j](1≤j≤m)时,将A[j]后移一位;否则将temp存入A[j+1]中。重复上述过程继续插入A[m+2],A[m+3],……,A[m+n],最终A[]中元素整体有序。

(2)算法描述

void Insert(int A[],int m,int n){int i,j;int temp;    //辅助变量,用来暂存待插入元素。for(i=m+1;i<=m+n;i++) {    //将A[m+1…m+n]插入到A[1…m]中。temp=A[i];for(j=i-1;j>=1&&temp<A[j];j--)A[j+1]=A[j];    //元素后移,以便腾出一个位置插入temp。A[j+1]=temp;    //在j+1位置插入temp。}
}

(3)算法时间和空间复杂度
①本题的规模由m和n共同决定。取最内侧循环中A[j+1]=A[j];这一句作为基本操作,其执行次数在最坏的情况下为:f(m,n)=(m+m+n-1)n/2=mn+n2/2–n/22
②算法额外空间中只有一个变量temp,因此空间复杂度为O(1)。

第二题

问题

已知递增有序的单链表A,B(A,B中元素个数分别为m,n且A,B都带有头结点)分别存储了一个集合,请设计算法以求出两个集合A和B的差集A-B(即仅由在A中出现而不在B中出现的元素所构成的集合)。将差集保存在单链表A中,并保持元素的递增有序性。

(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间复杂度。

解答

(1)算法基本设计思想:
只需从A中删去A与B中共有的元素即可。由于两个链表中元素是递增有序的所以可以这么做:设置两个指针p, q开始时分别指向A和B的开始结点。循环进行以下判断和操作,如果p所指结点的值小于q所指结点值,则p后移一位;如果q所指结点的值小于p所指结点的值,则q后移一位;如果两者所指结点的值相同,则删除p所指结点。最后p与q任一指针为NULL的时候算法结束。

(2)算法描述:

void Difference(LNode *&A, LNode *B) {LNode *p = A->next, *q = B->next; //p和q分别是链表A和B的工作指针。LNode *pre = A;LNode *r;while(p != NULL && q != NULL) {if(p->data < q->data) {pre = p;   //pre 为A中p所指结点的前驱结点的指针。p = p->next;  //A链表中当前结点指针后移。}else if (p->data > q->data)q = q->next;else {pre->next = p->next;    //B 链表中当前结点指针后移。r = p;    //处理A,B中元素值相同的结点,应删除。p = p->next;free(r);    // 删除结点。}}
}

(3)算法时间复杂度分析:
由算法描述可知,算法规模由m和n共同确定。算法中有一个单层循环,循环内的所有操作都是常数级的,因此可以用循环执行的次数作为基本操作执行的次数。可见循环执行的次数即为p, q两指针沿着各自链表移动的次数,考虑最坏的情况,即p, q都走完了自己所在的链表,循环执行m+n次。即时间复杂度为O(m+n)。

第三题

问题

设计一个算法,将顺序表中的所有元素逆置。

解答

clipboard.png

两个变量i,j指示顺序表的第一个元素和最后一个元素,交换i,j所指元素,然后i向后移动一个位置,j向前移动一个位置,如此循环,直到i与j相遇时结束,此时顺序表L中的元素已经逆置。

void reverse(Sqlist &L) {  //L要改变,用引用型int i,j;int temp; //辅助变量,用于交换for(i=1,j=L.length;i<j;i++,j--) {  //当i与j相遇时循环结束temp=L.data[i];L.data[i]=L.data[j];L.data[j]=temp;}
}

注意:本题中 for 循环的执行条件要写成i < j 而不要写成i != j 。如果数组中元素有偶数个则 i 与 j 会出现下图所示状态,此时i 继续往右走,j 继续往左走,会互相跨越对方,循环不会结束。

clipboard.png

第四题

问题

设计一个算法,从一给定的顺序表L中删除下标i到j(i≤j,包括i,j)之间的所有元素,假定i,j都是合法的。

解答

本题是顺序表删除算法的扩展,可以采用如下方法解决,从第j+1个元素开始到最后一个元素为止,用这之间的每个元素去覆盖从这个元素开始往前数第j-i+1个元素,即可完成删除i~j之间的所有元素。

本题代码如下:

void Delete(Sqlist &L,int i,int j) { //L要改变,用引用型。int k,l;l = j-i+1; //元素要移动的距离。for(k = j + 1;k <= L.length; k++) {L.data[k-l] = L.data[k]; //用第k个元素去覆盖它前边的第l个元素。}L.length -= l; //表长改变。
}

第五题

问题

有一个顺序表L,其元素为整型数据,设计一个算法,将L中所有小于表头元素的整数放在前半部分,大于的整数放在后半部分,数组从下表1开始存储。

解答

本题可以这样解决,先将L的第一个元素存于变量temp中,然后定义两个整型变量i,j。i从左往右扫描,j从右往左扫描。边扫描边交换。具体执行过程如下:

各步的解释如下:
①开始状态,temp = 2,i = 1; j = L.length
②j先移动,从右往左,边移动边检查j所指元素是否比2小,此时发现-1比2小,则执行L.data[i]=L.data[j];i++;(i中元素已经被存入temp所以可以直接覆盖,并且i后移一位,准备开始i的扫描)
③i开始移动,从左往右,边移动边检测,看是否i所指元素比2大,此时发现-7比2小,因此i在此位置是什么都不做。
④i继续往右移动,此时i所指元素为-3也比2小,此时什么都不做。
⑤i继续往右移动,此时i所指元素为5,比2大,因此执行L.data[j] = L.data[i]; j--(j中元素已被保存,j前移一位,准备开始j的扫描)
⑥j往左运动,此时j所指元素为6,比2大,j在此位置时,什么都不做。
⑦j继续往左移动,此时j==i,说明扫描结束。
⑧执行L.data[i] = temp;此时整个过程结束,所有比2小的元素被移到了2前边,所有比2大的元素被移到了2后边。

以上过程要搞清楚两点:
①i和j是轮流移动的,即当i找到比2大的元素时,将i所指元素放入j所指位置,i停在当前位置不,j开始移动。j找到比2小的元素,将j所指元素放在i所指位置,j停在当前位置不动,i开始移动如此交替直到i==j。
②每次元素覆盖(比如执行L.data[i] = L.data[j];)不会造成元素丢失,因为在这之前被覆盖位置的元素已经存入其他位置。由以上分析可写出如下算法:

void move(Sqlist &L) { //L要改变所以用引用型int temp;int i = 1,j = L.length;temp = L.data[i];while(i<j){/*关键步骤开始*/while(i < j&&L.data[j] > temp) j--; //j从左往右扫描,当来到第一个比temp小的元素时停止        ,并且每走一步都要判断i是否小于j,这个判断容易遗漏。if(i < j) { //检测看是否已仍满足i < j,这一步同样很重要L.data[i] = L.data[j]; //移动元素。i++; //i右移一位。}while(i < j&&L.data[i] < temp) i++; //与上边的处理类似。if(i < j) { //与上边的处理类似。L.data[j] = L.data[i]; //与上边的处理类似。j--;}/*关键步骤结束*/}L.data[i] = temp; //将表首元素放在最终位置。
}

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

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

相关文章

安卓第一次搭建C/S架构

1_数据库 2_服务端 服务端简单搭建准入门 使用json&#xff0c;导入jar包复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 提取码&#xff1a; 3afj 在项目中建一个文件夹并粘贴进去 json与list的互转&#xff1a; import com.alibaba.fastjson.JSON;import j…

面试官不讲武德,竟然问了我18个JVM问题!

前言GC 对于Java 来说重要性不言而喻&#xff0c;不论是平日里对 JVM 的调优还是面试中的无情轰炸。这篇文章我会以一问一答的方式来展开有关 GC 的内容。本文章所说的 GC 实现没有特殊说明的话&#xff0c;默认指的是 HotSpot 的。我先将十八个问题都列出来&#xff0c;大家可…

2月第3周国内域名商TOP10:爱名网排名升至第八

IDC评述网&#xff08;idcps.com&#xff09;02月26日报道&#xff1a;根据WebHosting.info公布的最新数据显示&#xff0c;在2月第3周&#xff0c;国内域名商域名总量十强总体呈下降趋势。其中&#xff0c;降幅最大的是DNSPod&#xff0c;净减16,762个。另外&#xff0c;中国数…

Android JSON数据与实体类之间的相互转化-------GSON的简单用法

Android JSON数据与实体类之间的相互转化-------GSON的用法1_Gson的导入1.1_方法一&#xff1a;直接导入jar包1.2_方法二&#xff1a;引入依赖2_json形式的字符串互转实体对象2.1_json字符串与单个实体对象互转2.2_json与list互转3_遇到的问题3.1_前后端对象成员变量类型不一致…

5种SpringBoot热部署方式,你用哪种?

来源 | my.oschina.net/ruoli/blog/1590148Spring Boot 中 5 种热部署方式如下&#xff1a;1、模板热部署2、使用调试模式Debug实现热部署3、spring-boot-devtools4、Spring Loaded5、JRebel接下来我们分别来看。1、模板热部署在 Spring Boot 中&#xff0c;模板引擎的页面默认…

ContextMenu长按事件

/* ContextMenu菜单就是长按某一个组件&#xff0c;就会在屏幕的中间弹出ContextMenu&#xff0c;这里设置为长按文本框弹出ContextMenu菜单*/public class MyContextMenu extends AppCompatActivity {/** Called when the activity is first created. */final static int CONT…

熬夜都要看完的 Spring 干货!

在 Java 后端框架繁荣的今天&#xff0c;Spring 无疑是最最最火热&#xff0c;也是必不可少的开源框架&#xff0c;像腾讯、阿里、字节跳动等一线互联网公司都选择 Spring 作为基础的开发框架。而 Spring 生态圈里最让人兴奋的莫过于 Spring Boot 框架。他简化了使用 Spring 的…

2014值得期待的Erlang两本新书

在2014年的开头就有这样一个令人振奋的好消息,Erlang有一本新书即将出版 《The Erlang Runtime System》,其作者happi在2013年3月份发布了这本书的写作计划:"The plan is to have the book done by the end of 2013 and published early 2014. ",出版方是O’Reilly,依…

页面分栏LayoutInflater

/* 页面分栏*/ public class TabDemo extends TabActivity {/** Called when the activity is first created. */Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);TabHost tabHost getTabHost();LayoutInflater.from(this).inf…

这么简单的三目运算符,竟然这么多坑?

最近在一个业务改造中&#xff0c;使用三目运算符重构了业务代码&#xff0c;没想到测试的时候竟然发生 NPE 的问题。重构代码非常简单&#xff0c;代码如下&#xff1a;// 方法返回参数类型为 Integer // private Integer code; SimpleObj simpleObj new SimpleObj(); // 其…

用好MySQL的21个好习惯!

前言每一个好习惯都是一笔财富&#xff0c;本文分SQL后悔药&#xff0c; SQL性能优化&#xff0c;SQL规范优雅三个方向&#xff0c;分享写SQL的21个好习惯&#xff0c;谢谢阅读&#xff0c;加油哈~1. 写完SQL先explain查看执行计划&#xff08;SQL性能优化&#xff09;日常开发…

第四章图像增强

第四章图像增强1_图像增强的概念2_空间域增强2.1_图像增强的点运算2.1.1_灰度变换2.1.2_直方图均衡化2.1.3 直方图规定化1_图像增强的概念 什么是图像增强&#xff1a;图像增强是采用一系列技术去改善图像的视觉效果,或将图像转换成一种更适合于人或机器进行分析和处理的形式。…

springboot发送qq邮件

springboot发送qq邮件1_开启邮箱相关权限并获取邮箱授权码2_实现功能2.1_添加mail的依赖2.1.1_创建工程时添加2.1.2_在工程中添加2.2_配置文件application.properties配置相关信息2.3_实现代码1_开启邮箱相关权限并获取邮箱授权码 进入账户 开启POP3/SMTP服务并生成授权码 …

Spring Cloud Alibaba 深度解密!

说说吧&#xff0c;程序猿们&#xff0c;你们还有谁不是“单身G”&#xff1f;想要“赢取”白富美&#xff0c;当上CTO&#xff0c;走上人生巅峰&#xff0c;不努力怎么可以&#xff1f;别人疯狂购物&#xff0c;你疯狂学习&#xff0c;努力30天&#xff0c;向阿里P6迈进&#…

安卓连接真机调试

安卓连接真机调试一、打开开发者模式二、打开USB调试三、最后连接数据线这里使用荣耀20pro为例一、打开开发者模式 点击版本号&#xff0c;多点几下直到打开开发者模式 二、打开USB调试 系统与更新——>开发人员选项 三、最后连接数据线 连接数据线并选择MIDI模式

3W字!带你玩转「消息队列」

1. 消息队列解决了什么问题消息中间件是目前比较流行的一个中间件&#xff0c;其中RabbitMQ更是占有一定的市场份额&#xff0c;主要用来做异步处理、应用解耦、流量削峰、日志处理等等方面。1. 异步处理一个用户登陆网址注册&#xff0c;然后系统发短信跟邮件告知注册成功&…

okhttp_utils的使用以及与服务端springboot交互中遇到的问题

okhttp_utils的使用以及与服务端springboot交互中遇到的问题1_okhttp_utils在Android studio中的引入方法2_okhttputils的使用举例3_get和post的简单使用3_图片的上传3.1_单张图片的上传3.1.1_获取安卓本地图片问题3.1.2_okhttputils上传图片代码3.1.3_服务端接收图片3.2_单张图…

算法系列之图--DFS

深度优先搜索使用的策略是&#xff0c;只要与可能就在图中尽量“深入”。DFS总是对最近才发现的结点v出发边进行探索&#xff0c;知道该结点的所有出发边都被发现为止。一旦v的所有出发边都被发现了&#xff0c;搜索就回溯到v的前驱结点&#xff08;v是经该结点才被发现的&…

这8种常见的SQL错误用法,你还在用吗?

来源 | yq.aliyun.com/articles/72501MySQL 在近几年仍然保持强劲的数据库流行度增长趋势。越来越多的客户将自己的应用建立在 MySQL 数据库之上&#xff0c;甚至是从 Oracle 迁移到 MySQL上来。但也存在部分客户在使用 MySQL 数据库的过程中遇到一些比如响应时间慢&#xff0c…

千万不要这样写代码!9种常见的OOM场景演示

《Java虚拟机规范》里规定除了程序计数器外&#xff0c;虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能&#xff0c;我们本文就来演示一下这些错误的使用场景。一. StackOverflowError1.1 写个 bugpublic class StackOverflowErrorDemo {public static v…