【计算机类职业资格】程序员面试-7及答案解析.doc
《【计算机类职业资格】程序员面试-7及答案解析.doc》由会员分享,可在线阅读,更多相关《【计算机类职业资格】程序员面试-7及答案解析.doc(31页珍藏版)》请在麦多课文档分享上搜索。
1、程序员面试-7 及答案解析(总分:100.00,做题时间:90 分钟)一、论述题(总题数:28,分数:100.00)1.如何找出数组中只出现一次的数字 (分数:3.00)_2.如何判断一个整数 x 是否可以表示成 n(n2)个连续正整数的和 (分数:3.00)_3.数组和链表的区别是什么 (分数:3.00)_4.何时选择顺序表、何时选择链表作为线性表的存储结构为宜 (分数:3.00)_5.如何使用链表头 (分数:3.00)_6.如何实现单链表的插入、删除操作 (分数:3.00)_7.如何找出单链表中的倒数第 k 个元素 (分数:3.00)_8.如何实现单链表反转 (分数:3.00)_9.如何从
2、尾到头输出单链表 (分数:3.00)_10.如何寻找单链表的中间结点 (分数:3.00)_11.如何进行单链表排序 (分数:3.00)_12.如何实现单链表交换任意两个元素(不包括表头) (分数:3.00)_13.如何检测一个较大的单链表是否有环 (分数:4.00)_14.如何判断两个单链表(无环)是否交叉 (分数:4.00)_15.如何删除单链表中的重复结点 (分数:4.00)_16.如何合并两个有序链表(非交叉) (分数:4.00)_17.什么是循环链表 (分数:4.00)_18.如何实现双向链表的插入、删除操作 (分数:4.00)_19.为什么在单循环链表中设置尾指针比设置头指针更好 (
3、分数:4.00)_20.如何删除结点的前驱结点 (分数:4.00)_21.如何实现双向循环链表的删除与插入操作 (分数:4.00)_22.如何在不知道头指针的情况下将结点删除 (分数:4.00)_23.如何统计一行字符中有多少个单词 (分数:4.00)_24.如何将字符串逆序 (分数:4.00)_25.如何找出一个字符串中第一个只出现一次的字符 (分数:4.00)_26.如何输出字符串的所有组合 (分数:4.00)_27.如何检查字符是否是整数?如果是,返回其整数值 (分数:4.00)_28.如何查找字符串中每个字符出现的个数 (分数:4.00)_程序员面试-7 答案解析(总分:100.00,
4、做题时间:90 分钟)一、论述题(总题数:28,分数:100.00)1.如何找出数组中只出现一次的数字 (分数:3.00)_正确答案:()解析:一个整型数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。要求时间复杂度是 O(n),空间复杂度是 O(1)。 如果本题对时间复杂度没有要求的话,最容易想到的方法就是首先对这个整型数组排序,然后从第一个数字开始遍历,比较相邻的两个数,从而找出这个只出现一次的数字,所以其时间复杂度最快为 O(nlogn)。由于时间复杂度与空间复杂度的限制,该种方法不可取,所以需要一种更高效的方式。题目强调只有一个数字出现一次,其他的出现了
5、两次,首先想到的是异或运算的性质:任何一个数字异或它自己都等于 0,根据这一特性,如果从头到尾依次异或数组中的每一个数字,因为那些出现两次的数字全部在异或中抵消掉了,所以最终的结果刚好是那个只出现一次的数字。 程序示例如下: #includestdio.h int findNotDouble(int a,int n) int result=a0; int i; for(i=1;in;+i) result=ai; return result; int main() int array=1,2,3,2,4,3,5,4,1; int len=sizeof(array)/sizeof(array0);
6、 int num=findNotDouble(array,len); printf(“%d/n“,num); return 0; 程序输出结果: 5 引申:如果题目改为整型数组中除了两个数字之外,其他的数字都出现了两次,如何求解这两个只出现一次的数? 在上述解决方案的基础上,如果能够把原数组分为两个子数组,在每个子数组中,包含一个只出现一次的数字,而其他数字都出现两次,问题就可以很容易地解决了:分别对两个子数组按照上述解决方案执行结果。 现在问题的难点就是如何划分为两个符合求解方案的子数组。首先从头到尾依次异或数组中的每一个数字,因为其他数字都出现了两次,在异或中全部抵消掉了,所以最终得到的结
7、果将是两个只出现一次的数字的异或结果。而这两个数字肯定不一样,那么这个异或结果肯定不为 0,也就是说在这个结果数字的二进制表示中至少就有一位为 1,否则就为 0 了。在结果数字中找到第一个为 1 的位的位置,记为第 N 位,此时以第 N 位是不是 1 为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第 N 位都为 1,而第二个子数组的每个数字的第 N 位都为 0。通过这种方法就可以把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。 程序示例如下: #includestdio.h void fmdOnce(int data,int n,int
8、int r1=0; for(int i=0;in;i+) r1=datai; int bitNum=0; while(!(r1 +bitNum; int flag=(1bitNum); num1=0; num2=0; for(int j=0;jn;j+) if(dataj else num2=dataj; int main() int array=1,2,3,2,4,3,5,1; int num1, hum2; findOnce(array,sizeof(array)/sizeof(array0),num1,num2); printf(“%d/n%d/n“,num1,num2); return
9、 0; 程序输出结果: 5 42.如何判断一个整数 x 是否可以表示成 n(n2)个连续正整数的和 (分数:3.00)_正确答案:()解析:假设 x 可以表示成 n(n2)个连续正整数的和,那么数学表达式如下:x=m+(m+1)+(m+2)+.+(m+n-1),其中 m 为分解成的连续整数中最小的那一个,由于 m 是大于等于 1 的正整数,可知x=(2m+n-1)n/2,变换之后 m=(2x/n-n+1)/2,由 m 的范围可以知道(2x/n-n+1)/21,以上就是 X和 n 的关系。给定一个 n,看是否 x 能分解成 n 个连续整数的和,可以判断是否存在 m,也就转换成(2x/n-n+1)
10、是否是偶数的问题。 判断一个数是否是偶数,是一个比较容易解决的问题,所以本题就迎刃而解了,程序示例如下: #inchudestdio.h #includemath.h int main() int m=0,n=0,start=0,end=0,flag=0; float temp=0.0; printf(“请输入被分解的数:“); scanf(“%d“, printf(“请输入需要被分解的数字的个数:“); scanf(“%d“, temp=(float)m/n-(float)(n-1)/2; if(temp=(int)temp) for(flag=1,start=(int)temp,end=s
11、tart+n;startend;start+) printf(“%d“,start); printf(“/n“); if(flag=0) printf(“没有符合条件的个数/n“); return 0; 程序输出结果: 请输入被分解的数:10 请输入需要被分解的数字的个数:4 1 2 3 43.数组和链表的区别是什么 (分数:3.00)_正确答案:()解析:数组与链表是两种不同的数据存储方式。链表的特性是在中间任意位置添加元素、删除元素都非常地快,不需要移动其他的元素。通常对于单链表而言,链表中每一个元素都要保存一个指向下一个元素的指针;而对于双链表,每个元素既要保存一个指向下一个元素的指针,
12、还要保存一个指向上一个元素的指针;循环链表则在最后一个元素中保存一个指向第一个元素的指针。 数组是一组具有相同类型和名称的变量的集合,这些变量称为数组的元素,每个数组元素都有一个编号,这个编号称为数组的下标,可以通过下标来区别并访问这些元素,数组元素的个数也称为数组的长度。 具体而言,数组和链表的区别主要表现在以下几个方面: 1)逻辑结构。数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况,即在使用数组之前,就必须对数组的大小进行确定。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。数组中插入、删除数据项时,需要移动其他数据项。而链表采用动态分配内存的形
13、式实现,可以适应数据动态地增减的情况,需要时可以用 new/malloc 分配内存空间,不需要时用 delete/free 将已分配的空间释放,不会造成内存空间浪费,且可以方便地插入、删除数据项。 2)内存结构。(静态)数组从栈中分配空间,对于程序员方便快速,但是自由度小。链表从堆中分配空间,自由度大,但是申请管理比较麻烦。 3)数组中的数据在内存中是顺序存储的,而链表是随机存储的。数组的随机访问效率很高,可以直接定位,但插入、删除操作的效率比较低。链表在插入、删除操作上相对数组有很高的效率,而如果要访问链表中的某个元素,那就得从表头逐个遍历,直到找到所需要的元素为止,所以链表的随机访问效率比
14、数组低。 4)链表不存在越界问题,数组有越界问题。数组便于查询,链表便于插入删除,数组节省空间但是长度固定,链表虽然变长但是占了更多的存储空间。 所以,由于数组存储效率高、存储速度快的优点,如果需要频繁访问数据,很少插入删除操作,则使用数组;反之,如果频繁插入删除,则应使用链表。两者各有用处。4.何时选择顺序表、何时选择链表作为线性表的存储结构为宜 (分数:3.00)_正确答案:()解析:顺序表按照顺序存储,即数据元素存放在一个连续的存储空间之中,实现顺序存取或(按下标)直接存取。链表按照链接存储,即存储空间一般在程序的运行过程中动态分配与释放,且只要存储器中还有空间,就不会产生存储溢出的问题
15、。 顺序表与链表各有短长,在实际应用中,应根据具体问题的要求和性质来选择使用哪一种存储结构,通常有以下几方面的考虑: 1)空间。顺序表的存储空间是静态分配的,链表的存储空间是动态分配的。顺序表的存储密度比链表大,当要求存储的线性表长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表;反之,当线性表长度变化大,难以估计其存储规模时,采用动态链表作为存储结构为好。 2)时间。顺序表是随机存取结构,若线性表的操作主要是进行查找,很少做插入和删除操作时,采用顺序表做存储结构为宜;反之,若需要对线性表进行频繁地插入或删除等的操作时,宜采用链表做存储结构。并且,若链表的插入和删除主要发生在表
16、的首尾两端,则采用尾指针表示的单循环链表为宜。 所以,不能笼统地说哪种实现更好,必须根据实际问题的具体需要,并对各个方面的优缺点进行综合评估,才能最终选择一种比较适合的实现方法。5.如何使用链表头 (分数:3.00)_正确答案:()解析:在回答这个问题前,首先弄清楚一个概念,什么是结点?简单地说,结点表示的就是数据域与指针域的和,数据域存储数据元素的信息,指针域指示直接后继存储位置,所以结点表示数据元素或数据元素的映像关系。 单链表的开始结点之前附设一个类型相同的结点,称之为头结点,头结点的数据域可以不存储任何信息(也可以存放如线性表的长度等附加信息),头结点的指针域存储指向开始结点的指针(即
17、第一个元素结点的存储位置)。如图所示为带头结点的单链表。 图 1 带头结点的单链表头结点的作用主要有以下两点: 1)对带头结点的链表,在表的任何结点之前插入结点或删除表中任何结点,所要做的都是修改前一结点的指针域,因为任何元素结点都有前驱结点。若链表没有头结点,则首元素结点没有前驱结点,在其前插入结点或删除该结点时操作会复杂些。 2)对带头结点的链表,表头指针是指向首结点的非空指针,因此空表与非空表的处理是一样的。 在实现运算时,需要动态产生出其头结点,并将其后继指针置为空。 void initial_List(node *L) L=(node*)malloc(sizeof(node); L-
18、next=NULL; 需要注意的是,开始结点、头指针、头结点并不是一个概念,它们是有区别的。开始结点是指链表中的第一个结点,也就是没有直接前趋的那个结点,而链表的头指针是指向链表开始结点的指针(没有头结点时),单链表由头指针唯一确定,因此单链表可以用头指针的名字来命名。图 2 所示链表的头指针为 head,则称该链表为链表 head,在定义链表变量时可以这样声明:node *head,而头结点是人为地在链表的开始结点之前附加的一个结点。有了头结点之后,头指针指向头结点,无论链表是否为空,头指针总是非空。而且头指针的设置使得对链表的第一个位置上的操作与在表其他位置上的操作一致(都是在某一结点之后
- 1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接下载带来的问题本站不予受理。
- 2.下载的文档,不会出现我们的网址水印。
- 3、该文档所得收入(下载+内容+预览)归上传者、原创作者;如果您是本文档原作者,请点此认领!既往收益都归您。
下载文档到电脑,查找使用更方便
5000 积分 0人已下载
下载 | 加入VIP,交流精品资源 |
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 职业资格 程序员 面试 答案 解析 DOC
