【计算机类职业资格】(Java)程序员面试-15及答案解析.doc
《【计算机类职业资格】(Java)程序员面试-15及答案解析.doc》由会员分享,可在线阅读,更多相关《【计算机类职业资格】(Java)程序员面试-15及答案解析.doc(28页珍藏版)》请在麦多课文档分享上搜索。
1、(Java)程序员面试-15 及答案解析(总分:100.00,做题时间:90 分钟)一、论述题(总题数:26,分数:100.00)1.如何找出单链表中的倒数第 k 个元素 (分数:4.00)_2.如何实现链表的反转 (分数:4.00)_3.如何从尾到头输出单链表 (分数:4.00)_4.如何寻找单链表的中间结点 (分数:4.00)_5.如何检测一个链表是否有环 (分数:4.00)_6.如何在不知道头指针的情况下删除指定结点 (分数:4.00)_7.如何判断两个链表是否相交 (分数:4.00)_8.栈与队列有哪些区别 (分数:4.00)_9.如何实现栈 (分数:4.00)_10.如何用 O(1)
2、的时间复杂度求栈中最小元素 (分数:4.00)_11.如何实现队列 (分数:4.00)_12.如何用两个栈模拟队列操作 (分数:4.00)_13.如何进行选择排序 (分数:4.00)_14.如何进行插入排序 (分数:4.00)_15.如何进行冒泡排序 (分数:4.00)_16.如何进行归并排序 (分数:4.00)_17.如何进行快速排序 (分数:4.00)_18.如何进行希尔排序 (分数:4.00)_19.如何进行堆排序 (分数:4.00)_20.各种排序算法有什么优劣 (分数:4.00)_21.如何用移位操作实现乘法运算 (分数:4.00)_22.如何判断一个数是否为 2 的 n 次方 (分
3、数:4.00)_23.如何求二进制数中 1 的个数 (分数:3.00)_24.如何寻找数组中的最小值与最大值 (分数:3.00)_25.如何找出数组中第二大的数 (分数:3.00)_26.如何求最大子数组之和 (分数:3.00)_(Java)程序员面试-15 答案解析(总分:100.00,做题时间:90 分钟)一、论述题(总题数:26,分数:100.00)1.如何找出单链表中的倒数第 k 个元素 (分数:4.00)_正确答案:()解析:为了找出单链表中的倒数第 k 个元素,最容易想到的方法是首先遍历一遍单链表,求出整个单链表的长度 n,然后将倒数第 k 个,转换为正数第 n-k 个,接下去遍历
4、一次就可以得到结果。但是该方法存在一个问题,即需要对链表进行两次遍历,第一次遍历用于求解单链表的长度,第二次遍历用于查找正数第n-k 个元素。 显然,以上这种方法还可以进行优化。于是想到了第二种方法,如果沿从头至尾的方向从链表中的某个元素开始,遍历 k 个元素后刚好达到链表尾,那么该元素就是要找的倒数第 k 个元素,根据这一性质,可以设计如下算法:从头结点开始,依次对链表的每一个结点元素进行这样的测试,遍历 k 个元素,查看是否到达链表尾,直到找到那个倒数第 k 个元素。此种方法将对同一批元素进行反复多次的遍历,对于链表中的大部分元素而言,都要遍历 k 个元素,如果链表长度为 n,该算法时间复
5、杂度为 O(kn)级,效率太低。 存在另外一种更高效的方式,只需要一次遍历即可查找到倒数第 k 个元素。由于单链表只能从头到尾依次访问链表的各个结点,因此,如果要找出链表的倒数第 k 个元素的话,也只能从头到尾进行遍历查找,在查找过程中,设置两个指针,让其中一个指针比另一个指针(虽然 Java 语言没有指针的概念,但是引用与指针有着非常相似的性质。为了便于理解,在后续的介绍中都采用指针的概念来介绍)先前移 k-1 步,然后两个指针同时往前移动。循环直到先行的指针值为 NULL 时,另一个指针所指的位置就是所要找的位置。程序代码如下: public Node findElem(Node head
6、, int k) if(k1 | kthis.length() return null; Node p1=head; Node p2=head; for(int i=0; ik-1; i+)/前移 k-1 步 p1=p1.next; while(p1!=null) p1=p1.next; p2=p2.next; return p2; 2.如何实现链表的反转 (分数:4.00)_正确答案:()解析:为了正确地反转一个链表,需要调整指针的指向,而与指针操作相关代码总是非常容易出错的。先举个例子看一下具体的反转过程,例如,i,m,n 是 3 个相邻的结点,假设经过若干步操作,已经把结点i 之前的指针
7、调整完毕,这些结点的 next 指针都指向前面一个结点。现在遍历到结点 m,当然,需要调整结点的 next 指针,让它指向结点 i,但需要注意的是,一旦调整了指针的指向,链表就断开了,因为已经没有指针指向结点 n,没有办法再遍历到结点 n 了,所以为了避免链表断开,需要在调整 m 的 next 之前要把 n 保存下来。接下来试着找到反转后链表的头结点,不难分析出反转后链表的头结点是原始链表的尾结点,即 next 为空指针的结点。下面给出非递归方法实现链表的反转的实现代码。 public void ReverseIteratively(Node head) Node pReversedHead=
8、head; Node pNode=head; Node pPrev=null; while(pNode!=null) Node pNext=pNode.next; if(pNext=null) pReversedHead=pNode; pNode.next=pPrev; pPrev=pNode; pNode=pNext; this.head=pReversedHead;3.如何从尾到头输出单链表 (分数:4.00)_正确答案:()解析:从头到尾输出单链表比较简单,通过借鉴的想法,要想解决本问题,很自然地想把链表中链接结点的指针反转过来,改变链表的方向,然后就可以从尾到头输出了,但该方法需要额外
9、的操作,是否还有更好的方法呢?答案是有。 接下来的想法是从头到尾遍历链表,每经过一个结点,把该结点放到一个栈中。当遍历完整个链表后,再从栈顶开始输出结点的值,此时输出的结点的顺序已经反转过来了。该方法虽然没有只需要遍历一遍链表,但是需要维护一个额外的栈空间,实现起来会比较麻烦。 是否还能有更高效的方法?既然想到了栈来实现这个函数,而递归本质上就是一个栈结构,于是很自然地又想到了递归来实现。要实现反过来输出链表,每访问到一个结点,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结果就反过来了。 具体实现代码如下: public void printListReversely(Node p
10、ListHead) if(pListHead!=null) printListReversely(pListHead.next); System.out.println(pListHead.data); 4.如何寻找单链表的中间结点 (分数:4.00)_正确答案:()解析:如何寻找单链表的中间结点?最容易想到的思路是先求解单链表的长度 length,然后遍历 length/2的距离即可查找到单链表的中间结点,但是此种方法需要遍历两次链表,即第一次遍历求解单链表的长度,第二次遍历根据索引获取中间结点。 如果是双向链表,可以首尾并行,利用两个指针一个从头到尾遍历,一个从尾到头遍历,当两个指针相遇时
11、,就找到了中间元素。以此思想为基础,如果是单链表,也可以采用双指针的方式来实现中间结点的快速查找。 具体而言,第一步,有两个指针同时从头开始遍历;第二步,一个快指针一次走两步,一个慢指针一次走一步;第三步,快指针先到链表尾部,而慢指针则恰好到达链表中部(快指针到链表尾部时,当链表长度为奇数时,慢指针指向的即是链表中间指针,当链表长度为偶数时,慢指针指向的结点和慢指针指向结点的下一个结点都是链表的中间结点)。 具体实现代码如下: public Node SearchMid(Node head) Node p=this.head; Node q=this.head; while(p!=null q
12、=q.next; return q;5.如何检测一个链表是否有环 (分数:4.00)_正确答案:()解析:定义两个指针 fast 与 slow,其中,fast 是快指针,slow 是慢指针,二者的初始值都指向链表头,slow 每次前进一步,fast 每次前进两步,两个指针同时向前移动,快指针每移动一次都要跟慢指针比较,直到当快指针等于慢指针为止,就证明这个链表是带环的单向链表,否则,证明这个链表是不带环的循环链表(fast 先行到达尾部为 NULL,则为无环链表)。具体实现代码如下: public boolean IsLoop(Node head) Node fast=head; Node s
13、low=head; if(fast=null) return false; while(fast!=null slow=slow.next; if(fast=slow) return true; return!(fast=null | fast.next=null); 上述方法只能用来判断链表是否有环,那么如何找到环的入口点呢?如果单链表有环,按照上述思路,当走得快的指针 fast 与走得慢的指针 slow 相遇时,slow 指针肯定没有遍历完链表,而 fast 指针已经在环内循环了 n 圈(n=1)。假设 slow 指针走了 s 步,则 fast 指针走了 2s 步(fast 步数还等于 s
14、 加上在环上多转的 n 圈),设环长为 r,则满足如下关系表达式: 2s=a+nr s=nr 设整个链表长 L,入口环与相遇点距离为 x,起点到环入口点的距离为 a,则满足如下关系表达式: a+x=Fir a+x=(n-1)r+r=(n-1)r+L-a a=(n-1)r+(L-a-x) (L-a-x)为相遇点到环入口点的距离,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是在链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。 具体实现代码如下: publieNode FindLoopPort(Node head) Node slow=head
15、, fast=head; while(fast!=null fast=fast.next.next; if(slow=fast)break; if(fast=null | fast.next=null) return null; slow=head; while(slow !=fast) slow=slow.next; fast=fast.next; return slow; 6.如何在不知道头指针的情况下删除指定结点 (分数:4.00)_正确答案:()解析:可以分为两种情况来讨论: 若待删除的结点为链表尾结点,则无法删除,因为删除后无法使其前驱结点的 next 指针置为空; 若待删除的结点不
16、是尾结点,则可以通过交换这个结点与其后继结点的值,然后删除后继结点。 具体实现代码如下: public boolean deleteNode(Node n) if(n=null | n.next=null) return false; int tmp=n.data; n.data=n.next.data; n.next.data=tmp; n.next=n.next.next; return true; 7.如何判断两个链表是否相交 (分数:4.00)_正确答案:()解析:如果两个链表相交,那么它们一定有着相同的尾结点,因此实现思路为:分别遍历两个链表,记录它们的尾结点,如果它们的尾结点相同,
17、那么这两个链表相交,否则不相交。具体实现代码如下: publie boolean isIntersect(Node h1, Node h2) if(h1=null | h2=null) retum false; Node tail1=h1; /找到链表 h1 的最后一个结点 while(tail1.next!=null) tail1=tail1.next; Node tail2=h2; /找到链表 h2 的最后一个结点 while(tail2.next!=null) tail2=tail2.next; return tail1=tail2; 由于这个算法只需要分别遍历一次两个链表,因此算法的时
18、间复杂度为 O(len1+len2),其中 len1 和 len2分别代表两个链表的长度。 引申:如果两个链表相交,如何找到它们相交的第一个结点? 首先分别计算两个链表 head1、head2 的长度 len1 和 len2(假设 len1len2),接着先对链表 head1 遍历(len1-len2)个结点到结点 P,此时结点 P 与 head2 到它们相交的结点的距离相同,此时同时遍历两个链表,直到遇到相同的结点为止,这个结点就是它们相交的结点。需要注意的是,在查找相交的第一个结点前,需要先判断两个链表是否相交,只有在相交的情况下才有必要去找它们的交点,否则根本就没有必要了。 程序代码如下
- 1.请仔细阅读文档,确保文档完整性,对于不预览、不比对内容而直接下载带来的问题本站不予受理。
- 2.下载的文档,不会出现我们的网址水印。
- 3、该文档所得收入(下载+内容+预览)归上传者、原创作者;如果您是本文档原作者,请点此认领!既往收益都归您。
下载文档到电脑,查找使用更方便
5000 积分 0人已下载
下载 | 加入VIP,交流精品资源 |
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 职业资格 JAVA 程序员 面试 15 答案 解析 DOC
