Java 开发校招面试考点汇总 四(算法、数据结构、设计模式、场景题部分)

前言

题目来自牛客网,答案是自己整理的,仅供参考。有些题目没有答案是因为存在类似的题目或者过于基础,所以不再给出答案。共同学习,共同进步,希望大家能拿到心仪的offer!

六、算法与数据结构

❤1、哈希

1、hashset存的数是有序的吗?

hashset继承的是set接口,set是无序集合。

2、Object作为HashMap的key的话,对Object有什么要求吗?

Hashmap不允许有重复的key,所以要重写它的hashcode和equal方法,以便确认key是否重复

3、一致性哈希算法

在日常工作中,经常有这样的情况,我们需要做hash,散列开数据到不同的区或节点。目标要的结果是要均匀散列,避免某个节点积累大量的数据,出现倾斜情况。
比如目前有N台机器,过来的数据key,需要做散列key%N,分发到对应的节点上。

一致性哈希算法原理:
为了解决hash倾斜难题,一致性算法是这样的,节点和节点形成一个环。比如
A->B->C->A,这样一个环。数字hash后落在环上,而不是落到某个node。比如落在a~b node之间,通过顺时针转,这个数字归b节点管。
但是如果节点很少,同样容易出现倾斜,负载不均衡问题。所以一致性哈希算法,引入了虚拟节点,在整个环上,均衡增加若干个节点。比如a1,a2,b1,b2,c1,c2,a1和a2都是属于A节点的。

通过让闭环上的节点增加,来平衡各个节点散列的值。

4、什么是hashmap?

5、Java中的HashMap的工作原理是什么?

https://blog.csdn.net/qq_38977097/article/details/88827217

6、hashCode()和equals()方法的重要性体现在什么地方?

保证key的唯一性

❤2、树

1、说一下B+树和B-树?

m 阶的 B+ 树和 B- 树主要区别有三:
( 1 )有 n 棵子树的结点中含有 n ( B- 树中 n-1 )个关键字;
( 2 ) B+ 树叶子结点包含了全部关键字信息,及指向含关键字记录的指针,且叶子结点本身依关键字大小自小到大顺序链接;( 3 ) B+ 树的非终端结点可以看成是索引部分,结点中只含其子树(根结点)中最大(或最小)关键字。 B+ 树的查找既可以顺序查找,也可以随机查找, B- 只能顺序查找。

2、怎么求一个二叉树的深度?手撕代码?

1.后序遍历,最长栈长即为树的深度
2.递归,最后比较即可
3.遍历求层,层次即为深度

3、算法题:二叉树层序遍历,进一步提问:要求每层打印出一个换行符

bfs遍历,节点附带所在层数

4、二叉树任意两个节点之间路径的最大长度

1.问题定义
如果我们把二叉树看成一个图,父子结点之间的连线看成是双向的,我们姑且定义“距离”为两节点之间边的个数。
写一个程序求一棵二叉树中相距最远的两个结点之间的距离
2.解法
计算一个二叉树的最大距离无外乎两种情况:
A. 路径经过左子树的最深结点,再通过根节点,最后到右子树的最深结点。
B. 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其最大者。

5、如何实现二叉树的深度?

static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
 
        public TreeNode(int val) {
            this.val = val;
        }
    }
 
    /**
     * 递归求深度
     * @param root
     * @return
     */
    public static int treeDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 计算左子树的深度
        int left = treeDepth(root.left);
        // 计算右子树的深度
        int right = treeDepth(root.right);
        // 树root的深度=路径最长的子树深度 + 1
        return left >= right ? (left + 1) : (right + 1);
    }

6、如何打印二叉树每层的节点?

/**
思路是用arraylist模拟一个队列来存储相应的TreeNode
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        ArrayList<TreeNode> queue = new ArrayList<>();
        if (root == null) {
            return list;
        }
        queue.add(root);
        while (queue.size() != 0) {
            TreeNode temp = queue.remove(0);
            if (temp.left != null){
                queue.add(temp.left);
            }
            if (temp.right != null) {
                queue.add(temp.right);
            }
            list.add(temp.val);
        }
        return list;
    }
}

7、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象必须实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)

❤3、遍历

1、编程题:写一个函数,找到一个文件夹下所有文件,包括子文件夹

import java.io.File;
public class Main {
    public static void main(String[] args) {
        File file = new File("D:\\360Downloads");        
        walk(file);        
    }
     
    private static 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{  
                    // 输出路径  
                    System.out.println(file);
                }  
    }  
}

2、二叉树 Z 字型遍历

❤4、链表

1、反转单链表

https://blog.csdn.net/moakun/article/details/79996966

2、随机链表的复制

https://www.jianshu.com/p/8b0688ed7afb

3、链表-奇数位升序偶数位降序-让链表变成升序

插入排序

4、bucket如果用链表存储,它的缺点是什么?

5、如何判断链表检测环

差速法

❤5、数组

1、寻找一数组中前K个最大的数

public class Test {
    private static int searchMax(int[] temp) {
        int max = temp[0];
        for (int i = 0; i < temp.length; i++) {
            if (temp[i] > max) {
                max = temp[i];
            }
        }
        return max;
 
    }
 
 
    public static void main(String[] args) {
        int[] a = {1, 4, 12, 8, 6, 98, 3, 4, 1, 12};
        int max = searchMax(a);
        int k = 5;
        //max加1否则是0-97,数组越界98
        int[] temp = new int[max + 1];
        for (int i = 0; i < a.length; i++) {
            //可能有相同的数字
            temp[a[i]]++;
        }
        int count = 0;
        for (int j = max; j >= 0; j--) {
            if (count == k) {
                break;
            }
            //可能有相同的所以不用if,用while
            while (temp[j] > 0) {
                count++;
                System.out.println(j);
                temp[j]--;
            }
        }
 
    }
}

2、求一个数组中连续子向量的最大和

public class TestArray {
    public static int FindGreatestSumOfSubArray(int[] array) {
        if (array.length==0 || array==null) {
            return 0;
        }
        int currentSum =0;     //存储当前连续n项的和
        int max = array[0];            //初始化第一个数为连续子元素最大和
        for (int i = 0; i < array.length; i++) {
            //核心部分,好好理解.
            if(currentSum<=0){      //如过当前连续n项的和小于等于0,则没必要与后面的元素相加
                currentSum = array[i];      //currentSum重新赋值
            }else{
                currentSum += array[i];     //如果currentSum的值大于0,则继续与后面的元素相加,
            }
            if(currentSum>max){         //每次改变currentSum的值都有与max进行比较
                max = currentSum;       //如果currentSum的值大于max,则将currentSum的值赋值给max
            }
        }
        return max;
    }
    public static void main(String[] args) {
        int[] array = {6,-3,-2,7,-15,1,2,2};
//        int[] array = {-6,-3,-2,-7,-15,-1,-2,-2};
        int result = FindGreatestSumOfSubArray(array);
        System.out.println("连续子元素的最大和为:"+result);
    }
}

3、找出数组中和为S的一对组合,找出一组就行

public class NumComberAll {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a[] = {2,3,3,2,2,4,1,4,-2,5,1};
		String b = "";
		fun(a, b, 11, 0, 5);
	}
	//递归搜索
	public static void fun(int a[],String b, int length, int  i, int s)
	{
		String temp = b;
		if(i>=length)
			return;
		//输出
		if(s==0)
			System.out.println(temp);
		//不取a[i]
		fun(a,temp, length, i+1, s);
		//取a[i]
		temp=temp+a[i];
		fun(a,temp, length, i+1, s-a[i]);
	}
}

4、一个数组,除一个元素外其它都是两两相等,求那个元素?

5、算法题:将一个二维数组顺时针旋转90度,说一下思路。

6、求质数(素数)

public static void main(String[] args) {
  int i,n,k=0;
     for (n = 3; n<=100; n++) {     //3~100的所有数
         i=2;
         while (i<n) {
             if (n%i==0)  break;  //若能整除说明n不是素数,跳出当前循环
             i++;
          }
 
          
      if (i==n) {     //如果i==n则说明n不能被2~n-1整除,是素数
             k++;             //统计输出数的个数
             System.out.print(i+ "\t ");
             if (k %6==0)    //每输出5个则换行
              System.out.println();
         }
     }
 }

❤6、排序

1、排序算法知道哪些,时间复杂度是多少,解释一下快排?

直接插入排序,选择排序,冒泡排序:O(n*n) ,快速排序,归并排序,堆排序:O(nlog2n), 希尔排序:O(n√n) ,基数排序:O(d(r+n)), 快速排序:每次选择一个枢纽值,比它大的放在右边,比它小的放在左边,每一趟排序都会使一个数放到最终的位置。

2、如何得到一个数据流中的中位数?

private int count = 0;
private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
private PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(15, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
});
 
public void Insert(Integer num) {
    if (count %2 == 0) {//当数据总数为偶数时,新加入的元素,应当进入小根堆
        //(注意不是直接进入小根堆,而是经大根堆筛选后取大根堆中最大元素进入小根堆)
        //1.新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
        maxHeap.offer(num);
        int filteredMaxNum = maxHeap.poll();
        //2.筛选后的【大根堆中的最大元素】进入小根堆
        minHeap.offer(filteredMaxNum);
    } else {//当数据总数为奇数时,新加入的元素,应当进入大根堆
        //(注意不是直接进入大根堆,而是经小根堆筛选后取小根堆中最大元素进入大根堆)
        //1.新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
        minHeap.offer(num);
        int filteredMinNum = minHeap.poll();
        //2.筛选后的【小根堆中的最小元素】进入大根堆
        maxHeap.offer(filteredMinNum);
    }
    count++;
}
 
public Double GetMedian() {
    if (count %2 == 0) {
        return new Double((minHeap.peek() + maxHeap.peek())) / 2;
    } else {
        return new Double(minHeap.peek());
    }
}

3、堆排序的原理是什么?

4、归并排序的原理是什么?

5、排序都有哪几种方法?请列举出来。

6、如何用java写一个冒泡排序?

❤7、堆与栈

1、堆与栈的不同是什么?

2、heap和stack有什么区别。

3、解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。

❤8、队列

1、什么是Java优先级队列(Priority Queue)?

优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索。无论何时调用remove方法,总会获得当前优先级队列中的最小元素,但并不是对所有元素都排序。它是采用了堆(一个可以自我调整的二叉树),执行增加删除操作后,可以让最小元素移动到根。

❤9、高级算法

1、id全局唯一且自增,如何实现?

id type primary key auto_increament

2、如何设计算法压缩一段URL?

哈夫曼编码压缩算法

3、为什么要设计后缀表达式,有什么好处?

便于用栈实现计算

4、LRU算法的实现原理?

七、设计模式

❤1、结构型模式

1、java中有哪些代理模式?

2、如何实现动态代理

3、IO流熟悉吗,用的什么设计模式?

主要运用了俩个设计模式,适配器和装饰者模式。 适配器模式:例如 InputStreamReader和OutputStreamWriter做了 InputStream/OutputStream字节流类到Reader/Write

❤2、创建型模式

1、介绍一下单例模式?懒汉式的单例模式如何实现单例?

❤3、行为型模式

1、介绍一下策略模式?

2、设计模式了解哪些,手写一下观察者模式?

❤4、模式汇总

1、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法

2、j2ee常用的设计模式?说明工厂模式。

3、开发中都用到了那些设计模式?用在什么场合?

singleton:单例,用来减少垃圾对象和缓存用
factory:工厂模式,用来解耦(呵呵,其实模式都是用来解耦的)
facade和decorator:封装接口
command:命令模式,传递
Iterator:用来遍历对象
Observer:用来监听状态变化(现在习惯用listener机制替代)
templete:模板模式,用来处理相同的操作步骤
strategy:策略模式,策略选择
proxy:用来附加功能,属性或隐蔽。
bridge也很实用,用来解耦工厂与产品搭配之类的选择

4、简述一下你了解的Java设计模式

八、场景题

❤1、场景题汇总

1、情景题:如果一个外卖配送单子要发布,现在有200个骑手都想要接这一单,如何保证只有一个骑手接到单子?

2、场景题:美团首页每天会从10000个商家里面推荐50个商家置顶,每个商家有一个权值,你如何来推荐?第二天怎么更新推荐的商家?
可以借鉴下stackoverflow,视频网站等等的推荐算法。

3、场景题:微信抢红包问题
悲观锁,乐观锁,存储过程放在mysql数据库中

4、场景题:1000个任务,分给10个人做,你怎么分配,先在纸上写个最简单的版本,然后优化。
全局队列,把1000任务放在一个队列里面,然后每个人都是取,完成任务。
分为10个队列,每个人分别到自己对应的队列中去取务。

5、场景题:保证发送消息的有序性,消息处理的有序性。

6、如何把一个文件快速下发到100w个服务器

7、给每个组分配不同的IP段,怎么设计一种结构使的快速得知IP是哪个组的?

8、10亿个数,找出最大的10个。
建议一个大小为10的小根堆。

9、有几台机器存储着几亿淘宝搜索日志,你只有一台2g的电脑,怎么选出搜索热度最高的十个搜索关键词?

10、分布式集群中如何保证线程安全?

11、给个淘宝场景,怎么设计一消息队列?

12、10万个数,输出从小到大?
先划分成多个小文件,送进内存排序,然后再采用多路归并排序。

13、有十万个单词,找出重复次数最高十个?

import java.util.*;
import java.util.Map.Entry;
import java.io.*;
import junit.framework.TestCase;
 
public class search { 
public static void main(String[] args) throws FileNotFoundException
{
System.out.println("Press any letter to start word count:");  
        Scanner s = new Scanner(System.in);  
        if (s.nextLine() == null) 
        {  
            s.close();  
            System.exit(0);  
        } else 
        {  
            s.close();  
        } 
Map<String,Integer> map=new TreeMap<String,Integer>();
File file=new File("test.txt");//将文本文件与代码放入同一目录下,所以只写了相对路径
Reader reader=null;
StringBuilder exist=new StringBuilder();
try
{
reader=new InputStreamReader(new FileInputStream(file));
int tmpchar;
while((tmpchar=reader.read())!=-1)
{
if(isCharacter(tmpchar))
{
exist.append((char)tmpchar);
}
else
{
Addword(exist.toString(),map);
exist=new StringBuilder();
}
}
}catch(IOException e)
{
e.printStackTrace();
}
List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
        Collections.sort(list,new Comparator<Map.Entry<String,Integer>>() 
        {
            public int compare(Entry<String,Integer> o1,Entry<String,Integer> o2) 
            {
                return (o2.getValue().compareTo(o1.getValue()));//降序排序
            }
        });
        int i=10;
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()&&i>0) 
        {
            String key=iter.next();
            System.out.println((String)key+":"+map.get(key));
            i--;
        }
}
public static void Addword(String str,Map<String,Integer> map)//是字母就append组成单词
{
str=str.toLowerCase();
Integer count=map.get(str);
if(count==null)
{
map.put(str,1);
}
else
{
map.put(str,count+1);
}
}
public static boolean isCharacter(int tmpchar)//判断是否是字母
{
if(tmpchar>=65&&tmpchar<=90)
{
return true;
}
else if(tmpchar>=97&&tmpchar<=122)
{
return true;
}
return false;
}
}
运行结果(所选文本是一篇以a开头的词汇,所以结果都是a开头的):
a:37
abbr:10
abbreviation:5
ability:4
able:4
abroad:3
absence:3
absent:2
absenteeism:2 
abolish:1 
  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值