java 数据结构与算法 面试题_Java面试题4-数据结构与算法基础

说一下几种常见的排序算法和分别的复杂度

倒排一个LinkedList

Collecionts.reverse(List> list)

什么是跳表

1577179803928-8d43c4d5-35d1-4ce8-9828-7801f8a4506b.png

如何确认一个链表有环?进一步,确认环的位置

这是一道很常见的面试问题,,只用两个变量通过O(n)的时间复杂度就可以解决。

Floyd cycle detection算法,也叫做tortoise and hare算法,龟兔算法吧。

http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare

以下内容为对思路重新梳理了一下,参考了stackoverflow论坛的讨论

http://stackoverflow.com/questions/2936213/explain-how-finding-cycle-start-node-in-cycle-linked-list-work

http://stackoverflow.com/questions/494830/how-to-determine-if-a-linked-list-has-a-cycle-using-only-two-memory-locations。

和thestoryofsnow的博客

http://blog.csdn.net/thestoryofsnow/article/details/6822576

代码来自thefutureisour

http://blog.csdn.net/thefutureisour/article/details/8174313

原文链接:https://blog.csdn.net/duxinyuhi/article/details/53379239

龟兔解法的基本思想可以用我们跑步的例子来解释,如果两个人同时出发,如果赛道有环,那么快的一方总能追上慢的一方。进一步想,追上时快的一方肯定比慢的一方多跑了几圈,即多跑的路的长度是圈的长度的倍数。

基于上面的想法,Floyd用两个指针,一个慢指针(龟)每次前进一步,快指针(兔)指针每次前进两步(两步或多步效果是等价的,只要一个比另一个快就行,从后面的讨论我们可以看出这一点。ps:考虑一个链表A有1000000个结点的环,链表B是有1000000个的非环的结点,然后再加一个只有3个结点的小环,如果兔子跑的更快点,即每次前进多于2步,那么能更快的检测链表A,但链表B就很慢,因为要一直绕圈等乌龟,所以选择2步是一个tradeoff)。如果两者在链表头以外的某一点相遇(即相等)了,那么说明链表有环,否则,如果(快指针)到达了链表的结尾,那么说明没环。

1579068145735-6fba268a-f3e2-40fa-b0a8-377784e9cca9.png

证明如下:

这样做的道理我用下图解释

假设起点到环的起点距离为m,已经确定有环,环的周长为n,(第一次)相遇点距离环的起点的距离是k。那么当两者相遇时,慢指针移动的总距离为i,因为快指针移动速度为慢指针的两倍,那么快指针的移动距离为2i

1) i = m + p * n + k

2) 2i = m + q * n + ki

其中,p和q分别为慢指针和快指针在第一次相遇时转过的圈数。

2 ( m + p * n + k ) = m + q * n + k

=> 2m + 2pn + 2k = m + nq + k

=> m + k = ( q - 2p ) n

只要有一组p,q,k满足这个式子,假设就成立了。

我们假设

p = 0

q = m

k = m n - m

那么我们证明如下

m + k = ( q - 2p ) n

=> m + mn - m = ( m - 2*0) n

=> mn = mn.

这时,i为

i = m + p n + k

=> m + 0 * n + mn - m = mn.

假设成立。

环的检测

环的检测是Floyd解法的第二部分。

一旦乌龟和兔子相遇,将慢指针移到链表起点,快指针还在他们相遇的地方,即离环的起点距离k的地方。然后慢指针和快指针同时移动,每次移动一步,那么两者再次相遇的地方就是环的起点。

证明如下:

让乌龟和兔子都同时移动m+k步,乌龟到了他们最初遇见的地方(远离环起点k的位置)

之前我们得到 m + k = (q - 2p) n

即兔子走了q-2p圈,也到了和乌龟同样的位置

现在我们不让乌龟走 m+k 步,让乌龟只走 m 步,兔子也后退k步,即到了环的起点,这是他们第一次相遇的地方。

当他们相遇时,乌龟走的步数就是环的地点在的位置。

求环的长度的问题,第一次相遇后,再次相遇时,走的距离就是环的长度。

如何遍历一棵二叉树

1579068263858-e8b0b87a-c87e-4cb6-9810-1bdec0cde08e.png

1579068281365-60b1a97d-a4a2-46d4-9e0d-8451c03fe463.png

二叉树的深度优先遍历和广度优先遍历

1579067506847-885991a3-4d78-4ca0-9ba8-6e324fe79e17.png

广度优先遍历

英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。对于上面的例子来说,广度优先遍历的 结果是:A,B,C,D,E,F,G,H,I(假设每层节点从左到右访问)。

先往队列中插入左节点,再插右节点,这样出队就是先左节点后右节点了。

广度优先遍历树,需要用到队列(Queue)来存储节点对象,队列的特点就是先进先出。例如,上面这颗树的访问如下:

首先将A节点插入队列中,队列中有元素(A);

将A节点弹出,同时将A节点的左、右节点依次插入队列,B在队首,C在队尾,(B,C),此时得到A节点;

继续弹出队首元素,即弹出B,并将B的左、右节点插入队列,C在队首,E在队尾(C,D,E),此时得到B节点;

继续弹出,即弹出C,并将C节点的左、中、右节点依次插入队列,(D,E,F,G,H),此时得到C节点;

将D弹出,此时D没有子节点,队列中元素为(E,F,G,H),得到D节点;

深度优先遍历

英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。对于上面的例子来说深度优先遍历的结果就是:A,B,D,E,I,C,F,G,H.(假设先走子节点的的左侧)。

深度优先遍历各个节点,需要使用到栈(Stack)这种数据结构。stack的特点是是先进后出。整个遍历过程如下:

先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点了。

首先将A节点压入栈中,stack(A);

将A节点弹出,同时将A的子节点C,B压入栈中,此时B在栈的顶部,stack(B,C);

将B节点弹出,同时将B的子节点E,D压入栈中,此时D在栈的顶部,stack(D,E,C);

将D节点弹出,没有子节点压入,此时E在栈的顶部,stack(E,C);

将E节点弹出,同时将E的子节点I压入,stack(I,C);

…依次往下,最终遍历完成。

HashSet的实现方式

HashSet概述:

HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素

堆和栈在内存中的区别是什么

栈内存存储的是局部变量而堆内存存储的是实体;

栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收

什么是深拷贝和浅拷贝

浅拷贝: 是一个传址,也就是把a的值赋给b的时候同时也把a的址赋给了b,当b(a)的值改变的时候,a(b)的值同时也会改变

深拷贝:深拷贝是指,拷贝对象的具体内容,二内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象页互相不影响,互不干涉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.栈和队列的共同特点是(只允许在端点处插入和删除元素) 4.栈通常采用的两种存储结构是(线性存储结构和链表存储结构) 5.下列关于栈的叙述正确的是(D) A.栈是非线性结构B.栈是一种树状结构C.栈具有先进先出的特征D.栈有后进先出的特征 6.链表不具有的特点是(B)A.不必事先估计存储空间 B.可随机访问任一元素 C.插入删除不需要移动元素 D.所需空间与线性表长度成正比 7.用链表表示线性表的优点是(便于插入和删除操作) 8.在单链表中,增加头结点的目的是(方便运算的实现) 9.循环链表的主要优点是(从表中任一结点出发都能访问到整个链表) 10.线性表L=(a1,a2,a3,……ai,……an),下列说法正确的是(D) A.每个元素都有一个直接前件和直接后件 B.线性表中至少要有一个元素 C.表中诸元素的排列顺序必须是由小到大或由大到小 D.除第一个和最后一个元素外,其余每个元素都有一个且只有一个直接前件和直接后件 11.线性表若采用链式存储结构时,要求内存中可用存储单元的地址(D) A.必须是连续的 B.部分地址必须是连续的C.一定是不连续的 D.连续不连续都可以 12.线性表的顺序存储结构和线性表的链式存储结构分别是(随机存取的存储结构、顺序存取的存储结构) 13.树是结点的集合,它的根结点数目是(有且只有1) 14.在深度为5的满二叉树中,叶子结点的个数为(31) 15.具有3个结点的二叉树有(5种形态) 16.设一棵二叉树中有3个叶子结点,有8个度为1的结点,则该二叉树中总的结点数为(13) 17.已知二叉树后序遍历序列是dabec,中序遍历序列是debac,它的前序遍历序列是(cedba) 18.已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历为(DGEBHFCA) 19.若某二叉树的前序遍历访问顺序是abdgcefh,中序遍历访问顺序是dgbaechf,则其后序遍历的结点访问顺序是(gdbehfca) 20.数据库保护分为:安全性控制、 完整性控制 、并发性控制和数据的恢复。 1. 在计算机中,算法是指(解题方案的准确而完整的描述) 2.在下列选项中,哪个不是一个算法一般应该具有的基本特征(无穷性) 说明:算法的四个基本特征是:可行性、确定性、有穷性和拥有足够的情报。 3. 算法一般都可以用哪几种控制结构组合而成(顺序、选择、循环) 4.算法的时间复杂度是指(算法执行过程中所需要的基本运算次数) 5. 算法的空间复杂度是指(执行过程中所需要的存储空间) 6. 算法分析的目的是(分析算法的效率以求改进) ............ .................

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值