Advertisement

秋招面经(后端开发) - 2021届

阅读量:

文章目录

  • 字节跳动批次 - 后端开发 - 技术研发方向
    • 字节跳动初试笔试题库

    • 字节跳动复试面试真题汇总

    • Java基础概念、算法题

    • Linux系统操作与应用实践

    • 网络技术原理及实践

    • 数据库系统设计与优化

    • 个人项目总结与优化

    • 数据结构学习笔记及其应用案例分析报告

    • 算法设计与实现练习集(Java版)

      • 字节提前批三面
    • shopee 后端开发

      • 笔试(2020.7.29)
      • 一面
      • 二面
    • 微信

      • 一面(2020.8.10)

      • 二面(2020.8.14)

      • 三面(2020.8.18)

        • 1、LRU
        • 2、表达式比较
        • 3、恢复 IP 地址
        • 4、
        • 5、
        • -----------------------
      • 四面(2020.8.21)

微信、字节和shopee已拿意向书。

字节跳动提前批 - 后端开发 - 技术中台方向

字节提前批一面

先来个个人介绍

实习经历概述

计网

数据库系统中使用的索引采用了哪种数据结构?B+树
在何种情况下才会采用哈希索引?通常存储在内存还是磁盘上?

个人项目中涉及了Redis、Kafka以及Elasticsearch等多种技术。
请问Redis的zset底层结构是怎样的?让我详细讲解一下跳表数据结构的相关知识。
Redis还依赖哈希表来实现特定应用场景是什么?
Redis采用持久化方式包括RDB和AOF两种方法;
当rdb完成或者在aof重写期间时,
子进程应该如何通知父进程?

Kafka机制;
消息发送的三类方法;
消费者组数量变化时的均衡分配机制;

操作系统的虚拟内存布局包括堆、栈以及从低地址到高地址存储的内容;其中堆用于长期运行的任务管理、静态数据存储以及函数调用返回信息的存放;栈则用于程序运行时的操作系统调用记录、局部变量的临时存储以及函数参数的传递;而内存中低地址到高地址存储的内容主要包括全局变量和动态分配的空间。
操作系统的进程栈与线程栈的主要区别在于其作用机制:进程栈主要用于操作系统为多任务处理而设计的数据结构管理方法,在资源调度与过程切换中发挥重要作用;而线程栈则是为单个线程服务的数据结构组织形式,在线程生命周期管理方面具有独特优势。

算法题
判断单链表有没有环,有的话找出入环节点

复制代码
    /** * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
    public ListNode detectCycle(ListNode head) {
        
    }
    }

我写的:

复制代码
    import java.util.Scanner;
    public class Main {
    public ListNode detechCycle(ListNode head) {
        if (head == null && head.next == null) {
            return null;
        }
        
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null && slow != fast) {
            slow = slow.next;
            fast = fast.next.next;
        }
        
        if (slow == fast) {
            fast = head;
            while (slow != fast) {
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        } else {
            return null;
        }
    }
    
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a = in.nextInt();
        System.out.println(a);
        System.out.println("Hello World!");
        
    }
    }

字节提前批二面

Java

volatile关键字与synchronized关键字-作用与用途上的差异;ReentrantLock类用于解决单线程问题时的同步需求而Condition类则用于处理多线程环境下的互斥事件等待问题;signal()函数常用于单个线程之间简单的信号传递而signalAll()函数则能够同时处理多个线程发出的信号建议根据具体的应用场景选择合适的函数进行调用

Linux

怎么看内存情况:free -h ;(刚好面试前看到了,你说巧不巧)
free -h 显示的 buffer 和 cache 有什么区别?(超出知识范围,瞎扯了一下 CPU 和内存间的高速缓存,内存和磁盘间的写缓存,还有redo log buffer,能水就水)

计网

DNS 工作流程:本地域 nameserver 服务器 - 根域 nameserver 服务器 - 顶级域 nameserver 服务器 - 权威域 nameserver 服务器;
DNS 使用的传输层协议:UDP;
如何防御 DNS 损害攻击:回答使用 HTTPS;
HTTPS 工作流程:数字签名 - 验证过程 - 采用对称加密算法进行通信。

数据库

事务涉及的四种隔离级别;
即使具备了可重复读特性,仍需采用串行化操作以避免幻读现象;
对于MVCC了解吗? 不清楚。

个人项目

如何提升网站运行效率:ThymeLeaf 模板引擎提供了高效的缓存机制;通过 Kafka 实现异步事件处理;Redis 用于缓存以及存储临时性较短的数据(例如验证码);Elasticsearch 则被用来执行全文检索(真的有人还在用MySQL全表扫描吗?手动狗头.jpg);采用线程池架构,在单个线程处理一个请求的同时为每个线程绑定当前请求对应的用户信息,并通过拦截器检查 cookie 信息等

当帖子数量庞大时,请问该怎么处理?(面试官可能是想让我采用分库分表的方法吗?但是当时我没有给出正确的解决方案)

数据结构

构建(heap)的时间复杂度为:当所有数据已存在时,则自下而上构建堆的时间复杂度为O(N);对于数据流输入的情况,则只能自上而下构建堆的时间复杂度为O(N \log N)

算法题

给定一个m×n的矩阵matrix,在其任何起始点上都可以向上、向下、向左或向右移动。每次移动到相邻位置时要求该位置上的元素值必须大于当前元素值。请计算该矩阵中所有可能递增路径中的最长路径长度。

我写的:

复制代码
    import java.util.Scanner;
    public class Main {
    
    public static int findLength(int[][] matrix, int[][] length, int i, int j) {
        if (length[i][j] != 0) {
            return length[i][j];
        }
        
        int result = 1;
        if (i - 1 >= 0 && matrix[i - 1][j] > matrix[i][j]) {
            result = Math.max(result, findLength(matrix, length, i - 1, j) + 1);
        }
        
        if (i + 1 < matrix.length && matrix[i + 1][j] > matrix[i][j]) {
            result = Math.max(result, findLength(matrix, length, i + 1, j) + 1);
        }
        
        if (j - 1 >= 0 && matrix[i][j - 1] > matrix[i][j]) {
            result = Math.max(result, findLength(matrix, length, i, j - 1) + 1);
        }
        
        if (j + 1 < matrix[0].length && matrix[i][j + 1] > matrix[i][j]) {
            result = Math.max(result, findLength(matrix, length, i, j + 1) + 1);
        }
        length[i][j] = result;
        return result;
    }
    
    public static int longestPath(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0] == null) {
            return 0;
        }
        
        int rowSize = matrix.length;
        int colSize = matrix[0].length;
        int[][] length = new int[rowSize][colSize];
        int result = 0;
        for (int i = 0; i < rowSize; i++) {
            for (int j = 0; j < colSize; j++) {
                result = Math.max(result, findLength(matrix, length, i, j));
            }
        }
        return result;
    }
    
    public static void main(String[] args) {
        //Scanner in = new Scanner(System.in);
        //int a = in.nextInt();
        //System.out.println(a);
        System.out.println("Hello World!");
    }
    }

字节提前批三面

之前面试中的不熟悉知识点有没有复习过?回答是肯定的。
具体来说,在之前的面试中讨论了MVCC(Mean Value Chain)、undo log等相关技术以及两个主要的锁协议。

一面中http 1.0/1.1/2.0的回答质量不高。回复后已查看并确认看过您的总结:<>

在TCP连接中,在传输速率方面涉及的具体因素包括哪些?具体包括:数据发送至缓存的速度;接收方从缓存中读取数据的速度;以及所采用的流量管理机制等。

编程语言,数据库,计网,操作系统,哪个最熟:瑟瑟发抖;

(中间有的问题忘了)

请编写以下 SQL 查询语句:基于以下表结构 T(id, name, age, sex, city),找出城市中男性平均年龄最高者。

复制代码
    select city
    from (select avg(age) as A, city
      from T
      where sex = "male"
      group by city) as Temp
    where A >= (select Temp.A from Temp);
    
    select city
    from (select avg(age) as A, city
      from T
      where sex = "male"
      group by city) as Temp
    order by A desc
    limit 0,1;

来做一个概率题试试看。假设某人患有某种疾病的风险为1%,使用一种检测试剂盒进行检测时的准确率为99%。如果检测结果显示呈阳性反应,请问在这种情况下,请问这个人患病的概率是多少?(虽然不太记得具体的计算方法了)

再来做两题:基于 [0,4) 的 rand4() 随机数发生器来生成相应的 rand6() 随机数序列。

一组包含32块大小不一的石块,通过天平进行比较,确定最重的那一块石块,最少需要多少次称量才能确定最重的石块?考官提示采用归并排序方法,具体计算后得出结论是31次

如果要找出最重的两块,请问需要多少次?我回答了46次。在网络上有人表示31次。觉得这个结果似乎不太合理。

shopee 后端开发

笔试(2020.7.29)

10题计算机相关的选择题
5题数学相关的选择题

3题编程题:

  1. 应用多重背包算法
  2. 基于提供的数据构建二叉搜索树,并返回所有的叶节点
  3. 按每组k个元素反转链表 - 来自LeetCode第2题
    (成功解答了2.8道题目)

一面

进程间的通信方式主要包含以下几种类型:首先分为管道和消息队列两大类;其中管道又可分为匿名管道和命名管道两种类型;而共享内存与信号量则是同步机制中的重要组成部分;此外还有基于信号量变量的同步机制;对于ipcs功能模块来说可以通过IPCS(Inter-Process Communication System)工具或接口功能查看当前系统中的IPC对象实例

内核空间和用户空间;为啥要这么区分;

分段机制、分页机制;

TCP四次挥手;

TCP 流量控制和拥塞控制;

发起请求至Shopee.com后将遵循以下步骤:进行DNS查询以获取服务器地址;随后完成TCP三次握手流程以建立连接通道;接着进行证书认证步骤以确认服务器身份;最后生成对称加密密钥用于后续的数据传输。如果请求采用HTTP/2.0协议,则服务器会主动发送流量控制参数或应用数据包以优化网络性能。

websocket 有了解吗:没有;

IO 多路复用的几种系统调用(select、poll、epoll),主要区别;

介绍一下红黑树;

介绍一下 B+树、B树;

Java中的多线程实现途径(即如何通过多线程来执行任务);如可采用Runnable接口、Callable接口以及继承自Thread类的方式。

MySQL的数据持久化手段主要包括redo log、binlog和undo log等技术;具体来说,在执行更新操作时如何确保数据的一致性和完整性。

ACID 是啥;

Redis 的 sorted set 底层的数据结构(跳表),原理;

探讨Kafka原理时,请阐述如何确保系统具备高可用性和高性能?这可以通过以下措施实现:采用分区机制以分片数据存储;实施主副本复制策略以实现数据冗余;利用顺序读取接口以优化I/O性能;同时确保所有消息仅存储在对应的分区主节点中一份。此外……

最后是一题简单题:

复制代码
    在字符串中找出连续最长的数字串
    样例输出
    
    输出123058789,函数返回值9
    
    输出54761,函数返回值5
    
     
    
    接口说明
    
    函数原型:
    
       unsignedint Continumax(char** pOutputstr,  char* intputstr)
    
    输入参数:
       char* intputstr  输入字符串;
    
    输出参数:
       char** pOutputstr: 连续最长的数字串,如果连续最长的数字串的长度为0,应该返回空字符串;如果输入字符串是空,也应该返回空字符串;  
    
    返回值:
      连续最长的数字串的长度
    
    
    输入描述
    输入一个字符串。
    
    输出描述
    输出字符串中最长的数字字符串和它的长度。如果有相同长度的串,则要一块儿输出,但是长度还是一串的长度
    
    示例1
    输入
    abcd12345ed125ss123058789
    输出
    123058789,9
复制代码
    import java.util.Scanner;
    public class Main {
    public static int read(char[] arr, int begin) {
        int cur = begin;
        while (cur < arr.length) {
            if (arr[cur] <= '9' && arr[cur] >= '0'){
                cur++;   
            } else {
                break;
            }
        }
        return cur;
    }
    
    public static void Continumax(String input) {
        if (input == null || input.length() == 0) {
            System.out.println(", 0");
        }
        
        char[] arr = input.toCharArray();
        int resultBegin = -1;
        int resultSize = 0;
        int i = 0;
        while (i < arr.length) {
            if (arr[i] <= '9' && arr[i] >= '0'){
                int end = read(arr, i);
                if (end - i > resultSize) {
                    resultSize = end  - i;
                    resultBegin = i;
                }
                i = end;
            } else {
                i++;
            }
    
        }
        
        if(resultSize > 0) {
            System.out.printf("%s, %d", input.substring(resultBegin, resultBegin + resultSize), resultSize);
        } else {
            System.out.println(", 0");
        }
    }
    
    public static void main(String[] args) {
        //Scanner in = new Scanner(System.in);
        //int a = in.nextInt();
        //System.out.println(a);
        String input = "abcd12345ed125ss123058789";
        Continumax(input);
    }
    }

二面

问实习;

在 ConcurrentHashMap 中的 get 和 put 方法是一种高效的数据操作方式。

对于web安全的知识掌握情况如何?主要涉及注入攻击以及权限管理方面的讲解;对于CSRF(跨站域请求伪造)这一概念尚不熟悉

讲讲 MVCC;(推荐看这篇: )

Kafka系统中partition的分配策略是指将同一主题下的每个partition按照特定规则分配到对应消费者组中的一个消费者;该系统中的负载均衡机制通过定期的任务重排来确保资源的均衡利用。

TCP 的 CLOSE_WAIT 和 TIME_WAIT 状态;
CLOSE_WAIT 的作用;

Linux 用什么命令看 tcp 的状态信息:netstat;

算法题:

  1. 对于一个数组进行排序,在其元素仅取值于{0,1,2}的情况下:我采用了类似于快速排序算法的设计思路;
  2. 寻找包含在给定字符串中的最长回文子串:我先概述了Manacher算法的基本原理,并深入探讨了基于动态规划的求解方法。

你觉得你技术方面最大的优势是什么?
职业规划?

请问环节为?进入后如何选择部门?公司采用统一招聘方式。在员工入职时进行分配安排。这将充分考虑员工个人意愿。

微信

一面(2020.8.10)

上来先做两题:

  1. 倒转单链表(在原链表上倒转)
复制代码
    struct LinkNode {
      int value;
      struct LinkNode * next;
    };
    void reverseList( struct LinkNode * head );

在操作过程中须注意以下几点:首先,在链表反转操作完成后(即完成之后),head指针依旧指向链表头部位置(即原始链表的头节点)。其次,在实际应用中,请确保原始链表的头节点对象在反转操作完成后仍能作为新的头部引用(具体来说,则可以通过对相关节点进行值域修改等方式实现这一目标)。

复制代码
    import java.util.Scanner;
    public class Main {
    
    public static void reverseList(LinkNode head) {
        if (head == null || head.next == null) {
            return;
        }
        
        // 从第二个节点开始翻转
        LinkNode cur = head.next;
        LinkNode next = null;
        // 创建一个新节点,作为翻转后的最后一个节点
        LinKNode pre = new LinkNode();
        pre.value = head.value;
        
        while (cur != null) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        
        head.value = pre.value;
        head.next = pre.next;
    }
    
    public static void main(String[] args) {
    }
    }

数字从1到N均匀分布在长度为N加一的数组中,并存在一个元素恰好出现一次,请找出该重复元素? 时间复杂度为O(N),空间复杂度为O(1)

复制代码
    用异或来做就完事了

(面试官是之前实习的 leader)
阐述Java中的new与C++中的malloc()有何异同;
深入探讨Java垃圾回收机制的相关知识;
区分进程与线程的本质差异;
比较进程切换与线程切换所需资源有何不同?
分析epoll()与select()在实现原理上的差异;
详细说明TCP三次握手与四次挥手的作用机制;
探讨是否允许两个进程分别绑定TCP和UDP在同一端口上?
解析TIME_WAIT状态在系统中的具体应用价值。

二面(2020.8.14)

介绍Elasticsearch的原理时,提到了分词技术和倒置索引机制; 详细探讨了Java语言中的HashMap和TreeMap数据结构及其特性; 简述数据库中常见的索引类型及作用; 进入深入分析,探讨了平衡二叉搜索树的构建原理及其在数据结构中的应用价值;

在输入www.qq.com后所经历的过程包括以下几个方面:先是介绍DNS的基本概念;接着讲解HTTP和HTTPS的区别及各自的特点;随后深入探讨HTTP/2.0的标准更新内容;之后分析TCP/IP协议体系的基础知识;最后详细讨论链路层中的ARP协议的作用。

在单机环境中存在多个数据文件的情况下(algorithm question: multiple files on a single machine)

2、假设有一个数组,其中元素先递增后递减,例如 [1, 3, 5, 4, 2]。请找到该数组中最大元素的索引位置:
我采用了一种二分法来实现这一目标:

复制代码
    public class Main {
    
    public static int find(int[] nums, int left, int right) {
        if (left == right) {
            return left;
        }
    
        int mid = left + ((right - left) >> 1);
        if (nums[mid] > nums[mid + 1]) {
            return find(nums, left, mid);
        } else {
            return find(nums, mid + 1, right);
        }
    }
    
    public static int find(int[] nums) {
        if(nums == null || nums.length == 0) {
            return -1;
        }
    
        return find(nums, 0, nums.length - 1);
    }
    
    public static void main(String[] args) {
        int[] nums = new int[]{10, 15, 20, 20, 21,  22, 35,  20, 10, 9, 8, 7, 6};
        System.out.println(find(nums));
    }
    }

三面(2020.8.18)

一共面了三个小时,前两个小时做题,最后一个小时问答。我人都傻了。

总共布置了5道题目,在调试测试用例时遇到了不少问题,并且由于面试官更换试题而耽误了一些时间。最终只完成了前4道题目中的大部分内容,并对最后一道题目仍需进一步完善。

1、LRU

复制代码
    /*
    1. 某操作系统采用 LRU 作为内存页面置换算法。
    假设初始内存为空,现给定将访问的内存页序列 pages, 序列长度 page_cnt 和内存总容量(页面数) mem,请返回缺页中断的次数。
    例如:序列 pages = 1, 2, 3, 2, 1, 4; 内存 mem = 2
    返回:5
    int check_page_faults(int pages[], int page_cnt, int mem);
    */
    
    import java.io.*;
    import java.util.*;
    
    class LRU {
      class Node{
    int key;
    Node pre;
    Node next;
    
    Node(int key, Node pre, Node next) {
      this.key = key;
      this.pre = pre;
      this.next = next;
    }
      }
      
      int capacity;
      int size;
      Node head = new Node(-1, null, null);
      Node tail = new Node(-1, null, null);
      
      Map<Integer, Node> map = new HashMap<>();
      
      {
    head.next = tail;
    tail.pre = head;
    size = 0;
      }
      
      public LRU(int capacity) {
    if (capacity <= 0) {
      throw new IllegalArgumentException();
    }
    this.capacity = capacity;
      }
      
      public boolean access(int key) {
    boolean result = false;
    
    Node node = map.get(key);
    if (node != null) {
      // 命中
      result = true;
      moveToHead(node);
    } else {
      // 缺页
      if (size == capacity) {
        // LRU 已满
        Node last = removeLast();
        map.remove(last.key);
        size--;
      }
      
      node = new Node(key, null, null);
      map.put(key, node);
      addToHead(node);
      size++;
    }
    return result;
    
      }
      
      private void addToHead(Node current) {
    Node oldHead = head.next;
    head.next = current;
    current.pre = head;
    current.next = oldHead;
    oldHead.pre = current;
      }
      
      private void remove(Node node) {
    Node pre = node.pre;
    Node next = node.next;
    pre.next = next;
    next.pre =  pre;
      }
      
      private void moveToHead(Node node) {
    remove(node);
    addToHead(node);
      }
      
      private Node removeLast() {
    if (size == 0) {
      return null;
    }
    
    Node last = tail.pre;
    remove(last);
    return last;
      }
      
      
    }
    
    public class MyCode {
      
      public static int check_page_faults(int pages[], int page_cnt, int mem) {
    int result = 0;
    
    if (pages == null || page_cnt <= 0 || pages.length < page_cnt) {
      return result;
    }
    
    LRU lru = new LRU(mem);
    for (int i = 0; i < page_cnt; i++) {
      boolean isIn = lru.access(pages[i]);
      if (!isIn) {
        result++;
      }
    }
    
    return result;
      }
      
      public static void main (String[] args) {
    	int[] pages = new int[]{1, 1, 1,1,1,1};
    int mem = 2;
    
    System.out.println(check_page_faults(pages, pages.length, mem));
      }
    }

2、表达式比较

注意:这里不可以简单地将 a-z 视为 1-26 来处理;这样操作的话, 第五个例子就会出错.

复制代码
    /*
    2. 检查两个表达式是否等价。表达式仅包含小写字母 'a'-'z', '+', '-', '(', ')',且表达式里的未知数仅有一个字符。
    例如:
    1) exp1 = "a+b+c-a", exp2 = "(b+c)", result: true
    2) exp1 = "a-b-c", exp2 = "a-(b+c)", result: true
    3) exp1 = "a-b+c", exp2 = "a-(b+c)", result: false
    4) exp1 = "a-b+c", exp2 = "a-(b-(c-d)-d)", result: true
    5) exp1 = "a+d", exp2 = "b+c", result: false
    
    bool check(const char* exp1, const char* exp2);
    */
    
    
    public class MyCode {
      
      public static int process(char[] arr1, int begin, int[] count) {
    // int[] result = new int[26];
    
    int i = begin;
    while (i < arr1.length) {
      if (arr1[i] == '(') {
        
        // 处理括号情况
        int[] child = new int[26];
        int next = process(arr1, i + 1, child);
        
        for (int j = 0; j < 26; j++) {
          if (i > 0 && arr1[i - 1] == '-') {
            // 负号
            count[j] -= child[j];
          } else {
            // 括号前为正号
            count[j] += child[j];
          }
        }
        i = next;
      } else if (arr1[i] == ')'){
        i++;
        return i;
      } else {
        
        if (arr1[i] <= 'z' && arr1[i] >= 'a') {
          if (i > 0 && arr1[i - 1] == '-') {
            count[arr1[i] - 'a'] -= 1; 
          } else {
            count[arr1[i] - 'a'] += 1;
          }
        }
        i++;
      }
      
      
    }
    return i;
      }
      
      public static boolean check(String str1, String str2) {
    char[] arr1 = str1.toCharArray();
    char[] arr2 = str2.toCharArray();
    
    int[] result1 = new int[26];
    int[] result2 = new int[26];
    
    process(arr1, 0, result1);
    process(arr2, 0, result2);
    
    for (int i = 0; i < 26; i++) {
      if (result1[i] != result2[i]){
        return false;
      }
    }
    
    return true;
      }
      
      public static void main(String[] args) {
    String str1 = "a+b+c-a";
    String str2 = "(b+c)";
    System.out.println(check(str1, str2));
      
    String str3 = "a-b-c";
    String str4 = "a-(b+c)";
    System.out.println(check(str3, str4));
    
    String str5 = "a-b+c";
    String str6 = "a-(b+c)";
    System.out.println(check(str5, str6));
    
    String str7 = "a-b+c";
    String str8 = "a-(b-(c-d)-d)";
    System.out.println(check(str7, str8));
    
    String str9 = "a+d";
    String str10 = "b+c";
    System.out.println(check(str9, str10));
      }
    }

3、恢复 IP 地址

复制代码
    /*
    3. 给一个由数字组成的字符串,求出所有可能的 IP 地址。
    例如:给出字符串 "25525511135",所有可能的 IP 地址为:
    [  "255.255.11.135", "255.255.111.35"  ]
    vector<string> restore_ip_addrs(const string& s);
    */
    
    import java.util.*;
    
    public class Main1 {
    
    static void process(String s, int sectionNum, int begin, String ip, List<String> result) {
        if (sectionNum ==  4) {
            if (begin == s.length()) {
                result.add(ip.substring(0, ip.length() - 1));
            }
            return;
        }
    
        if (sectionNum > 4 || (4 - sectionNum) * 3 < (s.length() - begin)) {
            return;
        }
    
        for (int i = 1; i <= 3; i++) {
            if (begin + i > s.length()) {
                break;
            }
            String nextSection = s.substring(begin, begin + i);
            if (Integer.parseInt(nextSection) > 255) {
                return;
            } else {
                process(s, sectionNum + 1, begin + i, ip + nextSection + ".", result);
            }
        }
    }
    
    static List<String> restore_ip_addrs(String s) {
        List<String> result = new ArrayList<>();
    
        if (s == null || s.length() < 4 || s.length() > 12) {
            return result;
        }
    
        process(s, 0, 0, "", result);
        return result;
    }
    
    public static void main(String[] args) {
        String str = "25525511135";
    
        List<String> result = restore_ip_addrs(str);
    
        for (String s : result) {
            System.out.println(s);
        }
    
        Map<String, String> map = new HashMap<>();
        for(Map.Entry e : map.entrySet()) {
            e.getValue();
        }
    }
    }

4、

复制代码
    /*
    4. 对输入的数组按出现的频率进行排序,若出现频率一致则按数字升序排序。
    例如:1, 2, 4, 9, 4, 1, 4, 2, 结果为:4, 4, 4, 1, 1, 2, 2, 9
    
    void sort(int arr[], int n);
    */
    import java.util.*;
    
    class MyCode{
      static void sort(int[] arr, int n) {
    if (arr == null || arr.length < 0) {
      return;
    }
    
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < arr.length; i++) {
      Integer value = map.get(arr[i]);
      
      if (value == null) {
        map.put(arr[i], 1);
      } else {
        map.put(arr[i], value + 1);
      }
    }
    
    int[][] result = new int[map.size()][];
    int i = 0;
    for (Map.Entry<Integer, Integer> e : map.entrySet()) {
      result[i++] = new int[]{e.getKey(), e.getValue()};
    }
    
    Arrays.sort(result, (int[] a, int[] b) -> {
      if (a[1] == b[1]) {
        return a[0] - b[0];
      } else {
        return b[1] - a[1];
      }
    });
    
    int cur = 0;
    for (i = 0; i < result.length; i++) {
      for (int j = 0; j < result[i][1]; j++){
        arr[cur++] = result[i][0];
      }
    }
      }
      
      public static void main(String[] args) {
    int[] arr = new int[]{1, 2, 4, 9, 4, 1, 4, 2};
    sort(arr, arr.length);
    for(int i = 0; i < arr.length; i++) {
      System.out.printf("%d, ", arr[i]);
    }
      }
    }

5、

这题我还没做完,只贴个题目吧

复制代码
    /*
    5. 给定一个排序链表,删除所有重复的元素,只留下原链表中没有重复的元素。
    例如: 1->1->2->3->3->4->4->5->6->6->null, return: 2->5->null
    
    struct LinkNode {
      int value;
      struct LinkNode * next;
    };
    struct LinkNode* delete_duplicates(struct LinkNode* head);
    */

-----------------------

做完这些题目后稍作休息,在向操作系统、计算机网络以及Redis方面提问:(仅能回忆出部分内容)

请了解Redis的基本概念和应用领域;其内存架构采用了分页机制;由于其单线程设计能够高效利用I/O复用技术,因此即使处理耗时任务如生成rdb快照或修改aof文件也需要依赖子进程来完成

select / epoll;
在TCP协议中进行端到端通信的过程被称为握手过程;
在监听阶段未完成连接时,请具体说明如何采取措施抵御DDoS攻击。

四面(2020.8.21)

问的很深,把我问傻了。只记得部分问题:

询问了实习相关内容;
首先探讨的是内核态与用户态之间的区别及其原因;其次询问是否理解内核态的实现机制及其与底层CPU指令的关系;
(面试官指出共有多种多样的方式让我感到困惑)
进一步了解Unix式套接字的概念及其相关特性;
sleep()等定时机制的工作原理是什么以及其实现细节是怎样的;
如何将处于睡眠状态的过程或线程唤醒;

堆排序;

Mysql 联合索引的结构;

简单了解了一下后发现

在这里插入图片描述

全部评论 (0)

还没有任何评论哟~