Java开发技术面试考点--算法与数据结构

算法与数据结构

❤1、哈希

1、hashset存的数是有序的吗?
hashset继承的是set接口,set是无序集合。
2、Object作为HashMap的key的话,对Object有什么要求吗?
Hashmap不允许有重复的key,所以要重写它的hashcode和equal方法,以便确认key是否重复
3、一致性哈希算法
4、什么是hashmap?
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。 HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
5、Java中的HashMap的工作原理是什么?
HashMap类有一个叫做Entry的内部类。这个Entry类包含了key-value作为实例变量。 每当往hashmap里面存放key-value对的时候,都会为它们实例化一个Entry对象,这个Entry对象就会存储在前面提到的Entry数组table中。Entry具体存在table的那个位置是 根据key的hashcode()方法计算出来的hash值(来决定)
6、hashCode()和equals()方法的重要性体现在什么地方?
Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。

❤2、树

1、说一下B+树和B-树?
一个 m 阶的B树是一个有以下属性的树:
每一个节点最多有 m 个子节点
每一个非叶子节点(除根节点)最少有 ⌈m/2⌉ 个子节点
如果根节点不是叶子节点,那么它至少有两个子节点
有 k 个子节点的非叶子节点拥有 k − 1 个键
所有的叶子节点都在同一层
B树和B+树的区别
B+树中只有叶子节点会带有指向记录的指针,而B树则所有节点都带有,在内部节点出现的索引项不会再出现在叶子节点中。
B+树中所有叶子节点都是通过指针连接在一起,而B树不会。
B+树优点:
中间节点全是索引节点,一个是可以降低树的高度,另一个是一个中间节点可以索引到更多的记录
可以直接在叶子节点层横向遍历,b树想要遍历则需要叶子节点和上层节点不停往返。
2、怎么求一个二叉树的深度?手撕代码?
1.后序遍历,最长栈长即为树的深度
2.递归,最后比较即可
3.遍历求层,层次即为深度
3、算法题:二叉树层序遍历,进一步提问:要求每层打印出一个换行符
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public static void BST(TreeNode root) {
if (root == null) return;
Queue queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
while (size-- > 0) {
TreeNode top = queue.poll();
System.out.println(top.val + " ");
if (top.left != null) queue.offer(top.left);
if (top.right != null) queue.offer(top.right);
}
System.out.println();
}
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
BST(root);
}
4、二叉树任意两个节点之间路径的最大长度
递归,把后一个节点当叶节点,前一个节点当根节点
5、如何实现二叉树的深度?
①递归实现: 为了求树的深度,可以先求其左子树的深度和右子树的深度,可以用递归实现,递归的出口就是节点为空。返回值为 0;
②非递归实现: 利用层次遍历的算法,设置变量 level 记录当前节点所在的层数,设置变量 last 指向当前 层的最后一个节点,当处理完当前层的最后一个节点,让 level 指向+1 操作。设置变量 cur 记 录当前层已经访问的节点的个数,当 cur 等于 last 时,表示该层访问结束。 层次遍历在求树的宽度、输出某一层节点,某一层节点个数,每一层节点个数都可以采取类 似的算法。 树的宽度:在树的深度算法基础上,加一个记录访问过的层节点个数最多的变量 max,在访 问每层前 max 与 last 比较,如果 max 比较大,max 不变,如果 max 小于 last,把 last 赋值给 max;
6、如何打印二叉树每层的节点?
就一个队列实现,打印当前节点的时候把左右两个孩子加入队列中 ,依次弹出打印,直到队列为空
7、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
TreeSet和TreeMap排序时比较元素要求元素对象必须实现Comparable接口
Collections的sort方法比较元素有两种方法:
元素对象实现Comparable接口
实体类Dog

❤3、遍历

1、编程题:写一个函数,找到一个文件夹下所有文件,包括子文件夹
private void walk(File file)
{
if(file != null){
if(file.isDirectory()){
// 列出全部的文件
File f[] = file.listFiles();
if(f != null)
for(int i = 0; i < f.length; i++)
//递归调用自身
walk(f[i]);
}else{
// 输出路径
result.add(file);
}
}
}
2、二叉树 Z 字型遍历
使用栈
先从右到左,再从左到右,直至遍历完毕

❤4、链表

1、反转单链表
头插法逆置
2、随机链表的复制
尾插法
3、链表-奇数位升序偶数位降序-让链表变成升序
插入排序
4、bucket如果用链表存储,它的缺点是什么?
不支持随机访问,查找的时间复杂度是O(n)
5、如何判断链表检测环
快慢指针

❤5、数组

1、寻找一数组中前K个最大的数
把前k个数建成最小堆,然后将栈顶元素与剩余的比较,如果大于,则交换,并调整最小堆,重复这个过程
2、求一个数组中连续子向量的最大和
定义一个sum用于保存累加和,sum初始值为0,每次累加数组的第i个数,如果sum小于0了,就说明之前的总和会对之后的加和起到副作用,这时直接把sum置零。以下是代码实现 int max_sum(vector& vec) { if(vec.size() <= 0) { return (1 << 31); } int max = vec[0]; int sum = 0; for(int i = 1; i <= vec.size()-1 ; i++) { sum = sum + vec[i]; max = sum > max ? sum :max ; if(sum < 0) { sum = 0; } } return max; }
3、找出数组中和为S的一对组合,找出一组就行
4、一个数组,除一个元素外其它都是两两相等,求那个元素?
5、算法题:将一个二维数组顺时针旋转90度,说一下思路。
必须是方阵,把第一行变成最后一列,第二行变成倒数第二列,以此类推吧

❤6、排序

1、排序算法知道哪些,时间复杂度是多少,解释一下快排?
直接插入排序,选择排序,冒泡排序:O(n*n) 快速排序,归并排序,堆排序:O(nlog2n) 希尔排序:O(n√n) 基数排序:O(d(r+n)) 快速排序:每次选择一个枢纽值,比它大的放在右边,比它小的放在左边,每一趟排序都会使一个数放到最终的位置。
2、如何得到一个数据流中的中位数?

3、堆排序的原理是什么?
1.先使用makeheap()创建最大堆或最小堆,
2.交换arr[0]和arr[last-1],
3.依据最大堆或最小堆来调整堆的顺序,
4.重复步骤2,3直到排序完成。
4、归并排序的原理是什么?
先拆开,拆完了两两比较然后合并。然后一大堆两个元素的,在两两比较,合成四个的。。。。合成一个,完成。 比较:abc,def。ad比较,a小,然后bd比较,d小,然后be比较。。。
5、排序都有哪几种方法?请列举出来。
冒泡排序,快速排序,插入排序,选择排序,希尔排序,堆排序。基数排序,桶排序,计数排序。
6、如何用java写一个冒泡排序?
外层循环i从n-1到1,内层循环j从0到i,判断相邻元素,前者大于后者就交换。

❤7、堆与栈

1、堆与栈的不同是什么?
要点:堆:顺序随意 栈:后进先出(Last-In/First-Out)
1.堆栈空间分配
①栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
②堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
2.堆栈缓存方式
①栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
②堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
3.堆栈数据结构区别
①堆(数据结构):堆可以被看成是一棵完全二叉树树,如:堆排序。
②栈(数据结构):一种先进后出的数据结构。
2、heap和stack有什么区别。
stack是由系统自动释放空间,heap要手动释放。
3、解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。
栈区:
保存一个4字节的heap内存地址(对象引用->定位该对象实例在heao中的位置)、对象方法和基础数据类型的对象
一个线程包含一个栈,私有不共享。由jvm自动分配释放
栈有三个部分:1.基本类型变量区 2.执行环境上下文 3.操作指令区
堆区:
保存对象的实例(属性值,属性类型,对象本身类型标记等)
jvm中只有一个堆区,被所有的线程共享,存储的对象由程序员分配释放
静态区/方法区:
包含的是整个程序中永远唯一的元素,class、static变量
所有线程共享

❤8、队列

1、什么是Java优先级队列(Priority Queue)?
说白了就是java的min-heap, 不过可以通过修改comparator方法,实现不同的需求

❤9、高级算法
1、题目:
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted.
Could you do both operations in O(1) time complexity?
2、id全局唯一且自增,如何实现?
3、如何设计算法压缩一段URL?
4、为什么要设计后缀表达式,有什么好处?
5、LRU算法的实现原理?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值