一面 80min

  1. http和https的区别
  2. https用到了哪些加密技术
  3. http使用到了哪些其他协议?
  4. 讲一下dns过程。给一个网址www.bytedance.com,dns服务器如何逐级解析的
  5. 讲一下tcp四次挥手,time-wait干嘛的,close-wait干嘛的,在哪一个阶段
  6. Tcp粘包拆包问题
  7. TCP拥塞控制与流量控制区别
  8. Mysql了解吗,讲一下事务,那mysql是如何保证ACID的呢(答了undo-log,redo-log,加锁,mvcc),那讲一下MVCC
  9. 快照读在提交读和可重复读级别下有什么区别
  10. 你提到了隐藏列有一个DB_ROW_ID,是干嘛的?那假设有10个update,到第九个回滚了,DB_ROLL_PTR如何做的,那提交了是否更新DB_ROLL_PTR?
  11. 讲一下索引及其底层,非叶子节点存储的是什么,只有b+树索引吗?(MEMORY是hash索引)
  12. 算法题:给定一个字符串数组[“hello”,”max”,”aello”,”world”],search(String s),判断字符串数组中是否存在一个字符串s1使得:s修改1个字符变为s1
public class _修改字符 {
    private static String[] strs;
    public static void main(String[] args) {
        strs = new String[]{"hello", "max", "aello",  "world"};
        String s = "bello";
        boolean find = new _修改字符().search(s);
        System.out.println(find == true ? "存在" : "不存在");
    }

    public boolean search(String s){
        for (int i = 0; i < strs.length; i++){
        	// 用于标记不相同字符的个数
            int one = 0;
            // 如果待修改的字符串与目标字符串的长度不相同,则跳过后续判断
            if (strs[i].length() != s.length()) continue;
            for (int j = 0; j < strs[i].length(); j++){
                if (s.charAt(j) != strs[i].charAt(j)){
                    if (one == 0){
                    	// 对于第一个不相同的字符,个数+1
                        one++;
                    } else {
                    	// 不相同的字符个数超过一个,直接退出循环
                        one++;
                        break;
                    }
                }
            }
            /**
            如果相同的字符串也算的话,就相当于不动,比如字符'a'修改为字符'a',那么可以修改一下下
            面的判断,改为 if (one <= 1) return true;一样可以实现功能
            */
            if (one == 1) return true; // 如果当前字符串与目标字符串只有一个不相同,则找到
        }
        // 循环结束也没有找到修改一次可以变为目标字符串的字符串
        return false;
    }
}
  1. 算法题:二维数组,从左往右递增,从上到下递增,有重复数字,找一个数字是否存在于数组中。
public class _二维数组查找数字 {

    public static void main(String[] args) {
        int[][] nums = {{1, 2, 3, 3, 3, 4, 5, 8},
                        {2, 3, 4, 4, 4, 6, 6, 9},
                        {4, 4, 4, 5, 5, 14, 15, 15},
                        {5, 8, 11, 12, 12, 15, 20, 20}};
        int[] f = new int[25];
        for (int i = 0; i < 25; i++){
            f[i] = i;
        }
        for (int i = 0; i < 25; i++) {
            System.out.println(i + " = " + new _二维数组查找数字().find2(nums, i));
        }
    }

    // 暴力解法,时间复杂度O(n^2)
    public boolean find(int[][] nums, int k){
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums[0].length; j++) {
                if (nums[i][j] == k){
                    return true;
                }
            }
        }
        return false;
    }

    // 优化,基于二分思想,时间复杂度降至O(n)
    public boolean find2(int[][] nums, int k){
        int row = 0, col = nums[0].length - 1;
        while (row < nums.length && col >= 0){
            if (nums[row][col] == k){
                return true;
            } else if (nums[row][col] > k){
                col--;
            } else {
                row++;
            }
        }
        return false;
    }
}

二面 70min

  1. 用户自己写一个String类,会发生什么?
  2. Sleep()和wait()的区别?
  3. Object类里有哪些方法?
  4. 那讲一下equals()与hashcode(),什么时候重写,为什么重写,怎么重写?
  5. 给一道题,判断输出。
  6. tcp四次挥手,time-wait
  7. http状态码有哪些(1xx-5xx),那讲一下301与302的区别
  8. 讲一下Mysql聚集索引与非聚集索引,主键索引使用int与string有啥区别,你刚才说了索引底层b+树的结构,那么使用String会不会影响到这个结构
  9. 算法题:找出数字字符串中最长的连续上升子序列(连续上升:前后两数之差为1)(LeetCode 300变种)
public class _最长上升子序列_前后相差1 {
    public static void main(String[] args) {
        String s = "23426457829828";
        System.out.println(new _最长上升子序列_前后相差1().findLongestSequence(s));
    }

    public String findLongestSequence(String s){
        int n = s.length();
        int[] dp = new int[n];
        Arrays.fill(dp, 1);
        int len = 1;
        for (int i = 1; i < n; i++){
            char c = s.charAt(i);
            for (int j = 0; j < i; j++){
                char pre = s.charAt(j);
                if (c - pre == 1){
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            len = Math.max(len, dp[i]);
        }
        char[] res = new char[len];
        for (int i = n - 1; i >= 0; i--){
            if (len == dp[i]){
                res[--len] = s.charAt(i);
            }
        }
        return new String(res);
    }
}

三面 50min

  1. 项目(你的哪些技术能用到未来的工作上)
  2. Java多态,如何实现?动态绑定
  3. Hashmap底层,扩容机制,为什么到8转为红黑树,装载因子为什么0.75,你自己设计一个hashmap,如何确定装载因子
  4. Redis作为缓存的基本使用,redis数据结构及底层(c的char[]和redis String有啥区别)
  5. MySQL性能调优;为什么不用select *
  6. 算法1:arr[]数组,n个奇数,n个偶数,重排,奇数位置是奇数,偶数位置是偶数(从0开始),空间复杂度O(1),时间复杂度O(n)
void oddEven1(int a[],int left,int right)
{
	int i=left,j = right;
	int tmp = 0;
	while(i<j){
		while(i<=right && a[i] % 2 == 0)
			i++;
		while(j>=left && a[j] % 2 == 1)
			j--;
		if(i<j)
			tmp = a[i],a[i] = a[j], a[j] = tmp;
	}
 
	j = left + (right - left)/2;
	for(i=left+1;i <=j;i += 2)
		tmp = a[i],a[i] = a[right - i],a[right - i] = tmp;
}
 
void oddEven2(int a[], int left,int right)
{
	int i = left,j = right;
	int tmp = 0;
 
	while(i<=right){
		while(i<= right)
			if(i % 2 == 0 && a[i] % 2 ==1)
				break;
			else
				i++;
		while(j>=left)
			if(j % 2 == 1 && a[j] % 2 == 0)
				break;
			else
				j--;
		if(i<=right && j>= left)
			tmp = a[i],a[i] = a[j],a[j] = tmp;	
	} 
}
  1. 算法2:判断数组arr[]中是否存在2个数的异或为k(时间复杂度最优)
public class _判断数组中是否存在异或值为k {
    public static void main(String[] args) {
        int[] nums = {13, 322, 1, 3, 2, 5, 6,
                7, 8, 18, 19, 32, 64, 33};
        int[] res = new _判断数组中是否存在异或值为k().findXor2(nums,8);
        if (res.length == 2){
            System.out.println(Arrays.toString(res));
        } else {
            System.out.println("不存在");
        }
    }

    // 暴力解法, 时间复杂度O(n^2)
    public int[] findXor(int[] nums, int k){
        for (int i = 0; i < nums.length; i++){
            for (int j = i + 1; j < nums.length; j++){
                if ((nums[i] ^ nums[j]) == k){
                   return new int[]{nums[i], nums[j]};
                }
            }
        }
        return new int[0];
    }


    // 利用哈希表优化,时间复杂度O(n)
    public int[] findXor2(int[] nums, int k){
        Set<Integer> set = new HashSet<>();
        for (int num : nums){
            if (set.contains(num ^ k)){
                return new int[]{num, num ^ k};
            }
            set.add(num);
        }
        return new int[0];
    }
}
  1. 反问:部门业务?

四面 54min

  1. 项目
  2. 进程与线程区别,进程通信方式,说一下socket,socket在本机和在网络通信区别
  3. 多进程与多线程的区别以及使用场景
  4. 算法题:之字型打印二叉树
    解:以下面这棵树为例
  5. 主键是否是索引_算法

public class _之字形打印二叉树 {
    // 定义树的节点
    static class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        public TreeNode(){
            this.val = 0;
            this.left = null;
            this.right = null;
        }

        public TreeNode(int val) {
            this.val = val;
            this.left = null;
            this.right = null;
        }
    }
    public static void main(String[] args) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        // 建树
        TreeNode root = new TreeNode(5);
        TreeNode p1 = root.left = new TreeNode(3);
        TreeNode p2 = root.right = new TreeNode(4);
        p1.left = new TreeNode(1);
        p2.left = new TreeNode(2);
        p2.right = new TreeNode(8);
        new _之字形打印二叉树().printTree(root, result);
        System.out.println("result = " + result);
    }

    public List<List<Integer>> printTree(TreeNode root, List<List<Integer>> result){
    	// 层次遍历的思想,利用队列
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        // 控制方向
        boolean direction = false;
        while (!queue.isEmpty()){
        	// 记录当前层的节点个数
            int size = queue.size();
            List<Integer> list = new ArrayList<>();
            // 一个while循环走完就是一层的遍历结构
            while (size-- > 0){
                root = queue.poll();
                list.add(root.val);
                // 左节点不为空,加入队列
                if (root.left != null){
                    queue.offer(root.left);
                }
                // 右节点不为空,加入队列
                if (root.right != null){
                    queue.offer(root.right);
                }
            }
            // 每隔一层,反方向遍历该层
            if (direction){
                Collections.reverse(list);
            }
           	// 每遍历一层变换方向
            direction = !direction;
            result.add(list);
        }
        return result;
    }
}

输出结果如下:

主键是否是索引_字符串_02

  1. 场景题目:设计王者荣耀战力排行榜,显示某区服所有玩家战力排行情况,以及我自己的战力排行情况
  2. 反问

五面 35min

  1. 项目
  2. 讲一下https,为什么要先使用非对称加密,那非对称加密不能保证安全性吗?(能)
  3. 讲一下http,请求头,状态码
  4. 现在我们视频面试用到哪些协议(DNS,HTTP,HTTPS,TCP,UDP),UDP用在哪里
  5. 讲一下你了解的对称加密算法和非对称加密算法(DES,AES,RSA),非对称加密如何保证它的安全性(数论大数分解)
  6. xss攻击、cors攻击原理
  7. Mysql存储引擎的作用,事务隔离级别,分别存在什么问题
  8. Java如何保证多线程安全
  9. I/O多路复用讲一下,epoll优势在哪,为什么,epoll水平触发与边缘触发
  10. 算法题:二维数组顺时针旋转90度
public class _二维数组顺时针旋转90度 {
    public static void main(String[] args) {
        int[][] nums = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        print(nums);
        System.out.println();
//        nums = rotate1(nums);
//        print(nums);
//        System.out.println();
        rotate2(nums);
        print(nums);
        System.out.println();
    }
	
	// 该方法开辟了一个二维数组,做起来相对容易,但空间复杂度较高
    public static int[][] rotate1(int[][] matrix){
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] array = new int[m][n];
        for (int i = 0; i < m; i++){
            for (int j = 0; j < n; j++){
                array[i][j] = matrix[n - j - 1][i];
            }
        }
        return array;
    }

	// 进一步优化,原地旋转
    public static void rotate2(int[][] matrix){
        int m = matrix.length;
        int n = matrix[0].length;
        // 先将数组的上半部和下半部进行交换
        for (int i = 0; i < m / 2; i++){
            for (int j = 0; j < n; j++){
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[m - i - 1][j];
                matrix[m - i - 1][j] = tmp;
            }
        }
		// 交换完后对数组进行转置,这里只能对上三角或下三角进行交换
		// 操作, 不然数组又变回去了,不能实现转置操作
        for (int i = 0; i < m; i++){
            for (int j = 0; j < i; j++){
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = tmp;
            }
        }
    }

    public static void print(int[][] matrix){
        for (int i = 0; i < matrix.length; i++){
            for(int j = 0; j < matrix[0].length; j++){
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  1. 有实习经历吗?为什么不实习?
  2. 未来职业规划
  3. 讲一个你最有成就感的事(社团+科研)
  4. 说一个自己的优缺点
  5. 反问