牛客收集的腾讯面经


前言

收集腾讯的面经,不包含自己面的,记录自己不会/认为高频的

不知道什么G

键入一个网站,会发生什么

  • 域名解析;
  • 发起TCP的3次握手;
  • 建立TCP连接后发起http请求;
  • 服务器响应http请求,浏览器得到html代码;
  • 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等);
  • 浏览器对页面进行渲染呈现给用户。

该过程使用到的协议?

MySQL有什么函数

len、upper、lower

pow

datediff

SpringBoot加载的过程

  1. 整个spring框架启动分为两部分,构造SpringBootApplication对象和执行run方法

  2. 核心注解@SpringBootConfiguration标识启动类为配置类,@EnableAutoConfiguration通过内部@Import注解AutoConfigurationImportSelector.class实现自动装配,@ComponentScan默认扫描当前目录及子目录下的bean。

  3. SpringBootApplication的构造方法主要做了几件事

    • 根据是否加载servlet类判断是否是web环境

    • 获取所有初始化器,扫描所有META-INF/spring.factories下的ApplicationContextInitializer子类通过反射拿到实例,在spring实例启动前后做一些回调工作。

    • 获取所有监听器,同2,也是扫描配置加载对应的类实例。

    • 定位main方法

  4. run方法主要创建了配置环境、事件监听、启动应用上下文,其中rfresh方法贯穿springbean的生命周期,执行bean的生命周期的前后置钩子方法,并且处理spring的注解标注的类。在onRefresh中通过Java代码构建出tomcat容器并启动。

PCG

各种排序对比

排序算法 平均时间复杂度 最坏时间复杂度 最好时间复杂度 空间复杂度 稳定性
冒泡排序 O(n²) O(n²) O(n) O(1) 稳定
直接选择排序 O(n²) O(n²) O(n) O(1) 不稳定
直接插入排序 O(n²) O(n²) O(n) O(1) 稳定
快速排序 O(nlogn) O(n²) O(nlogn) O(nlogn) 不稳定
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定
希尔排序 O(nlogn) O(ns) O(n) O(1) 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定
计数排序 O(n+k) O(n+k) O(n+k) O(n+k) 稳定
基数排序 O(N*M) O(N*M) O(N*M) O(M) 稳定

MySQL 的存储引擎有哪些,常用的是哪个

索引常见面试题 | 小林coding (xiaolincoding.com)

IOC底层是怎么实现的

不知道

Linux指令:如何查看线程、

1、top -H

手册中说:-H : Threads toggle

加上这个选项启动top,top一行显示一个线程。否则,它一行显示一个进程。

2、ps xH

手册中说:H Show threads as if they were processes

这样可以查看所有存在的线程。

数值范围0-40亿的数如何排序

bitmap,对应位置

协程

协程是比线程更小的一种执行单元,你可以认为是轻量级的线程,线程的调度是在操作系统中进行的,而协程调度则是在用户空间进行的,是开发人员通过调用系统底层的执行上下文相关api来完成的,有些语言,比如nodejs、go在语言层面支持了协程,而有些语言,比如C,需要使用第三方库才可以拥有协程的能力。

java gc,类加载

guide

http和HTTPS异同

小林

mysql的缓存机制

bufferpool

HTTP没那么安全的例子

无法验证消息完整、无法验证对对省份等等

创建HTTPS的步骤

我的理解就是tcp三次+SLL四次

Nosql的缺点

  1. 一致性问题

NoSQL数据库通常采用最终一致性的策略,即在一段时间内达到一致状态,可以容忍一定的数据不一致性。在数据更新和复制过程中,可能会出现数据不一致的情况。对于一些对数据一致性要求较高的场景,如金融系统或事务处理系统,NoSQL数据库可能不适合。

  1. 查询能力限制

NoSQL数据库的查询能力相对较弱,通常只支持基本的查询操作。与传统关系型数据库相比,NoSQL数据库缺少复杂的查询操作和聚合函数。在需要进行复杂的数据查询和分析的场景中,NoSQL数据库的查询能力可能无法满足需求。

接口和抽象类的区别

guide

介绍自己的优势

没优势

构建一个系统需要关注哪些方面

系统的性能
海量并发读取与写入

系统的安全性
系统的操作,数据的变更都应有日志进行跟踪
基于HTTPS的加密访问

系统的高可用性
微服务的部署方式
当服务出现不可用时需要对服务进行隔离,保障核心的服务不受影响,使得核心应用可以正常运行

系统的可运营性
指标监控
链路跟踪

系统的全球化性
多语言机制,适应海外及特定需求
多租户管理,对用户,子公司实现不同数据隔离和差异化处理

地方合规性
系统的架构设计是一项非常细致缜密的工作,前期需要对系统涉及的业务,关联到的业务以及企业的IT架构有足够的了解和认知,然后结合法律法规,利用当下企业提供的有限的条件进行设计。

系统高可用高容错的方案

就扯系统容灾吧

然后服务熔断服务降级来说

一个网页里一个图片链接,点开用了哪些协议

我觉得就是http等

Linux怎么查看网络状态

guide

Linux怎么查看文件位置,怎么查看程序的运行情况,怎么查看CPU使用情况,怎么查看进程pid

guide

Redis事务

总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

若在事务队列中存在语法性错误(类似于java的1/0的运行时异常),则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。

注意:已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚

解决哈希冲突的办法?

拉链和线性探测

以及二次哈希

:若当前key与原来key产生相同的哈希地址,则当前key存在该地址后偏移量为(1,2,3…)的二次方地址处
key1:hash(key)+0
key2:hash(key)+1^2
key3:hash(key)+2^2

腾讯安全

如何在300万个字符串中找到ip地址,如果找不到,如何找到前一个地址或者后一个地址

正则表达式吧,ip地址都有固定的格式,0-255,无前导0,三个小数点

如何设计一个高并发网络系统

io模型,缓存,数据库,容灾,负载均衡,协议等等就这几个方面

TEG

算法合集

2. 两数相加 - 力扣(LeetCode)

public class Main {
    public static void main(String[] args) {
        
    }

}
class ListNode{
    ListNode next;
    int val;
    ListNode(){}
    ListNode(int val){this.val=val;}
}
class Solution{
    public ListNode addNumbers(ListNode l1,ListNode l2)
    {
        ListNode dummy=new ListNode(0);
        ListNode p=dummy;
        int carry=0;
        while(l1!=null||l2!=null)
        {
            int a=l1==null?0:l1.val;
            int b=l2==null?0:l2.val;
            int sum=a+b+carry;
            carry=sum/10;
            sum%=10;
            p.next=new ListNode(sum);
            p=p.next;
            l1=l1==null?null:l1.next;
            l2=l2==null?null:l2.next;
        }
        if(carry==1) p.next=new ListNode(1);
        return  dummy.next;
    }

}

206. 反转链表 - 力扣(LeetCode)


package org.example;

import java.util.*;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Solution sl=new Solution();
        while(sc.hasNextInt())
        {
            int count=sc.nextInt();
            if(count==0)
            {
                System.out.println("list is empty");
                continue;
            }
            ListNode head=new ListNode(sc.nextInt());
            ListNode p=head;
            for(int i=1;i<count;i++)
            {
                p.next=new ListNode(sc.nextInt());
                p=p.next;
            }
            sl.print(head);
            head=sl.reverseList(head);
            sl.print(head);
        }
    }

}
class ListNode{
    ListNode next;
    int val;
    ListNode(){}
    ListNode(int val){this.val=val;}
}
class Solution{
    public ListNode reverseList(ListNode head)
    {
        ListNode cur=head;
        ListNode pre=null;
        while(cur!=null)
        {
            ListNode aft=cur.next;
            cur.next=pre;
            pre=cur;
            cur=aft;
        }
        return pre;
    }
    public void print(ListNode head)
    {
        StringBuilder sb=new StringBuilder();
        while(head!=null)
        {
            sb.append(head.val);
            sb.append(" ");
            head=head.next;
        }
        System.out.println(sb.toString().trim());
    }
}

83. 删除排序链表中的重复元素 - 力扣(LeetCode)


package org.example;

import java.util.*;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Solution sl=new Solution();
        while(sc.hasNextLine())
        {
            String a=sc.nextLine();
            ListNode head=new ListNode(a.charAt(0)-'0');
            ListNode p=head;
            for(int i=1;i<a.length();i++)
            {
                p.next=new ListNode(a.charAt(i)-'0');
                p=p.next;
            }
            sl.deleteSame(head);
            //.,...
        }
    }

}
class ListNode{
    ListNode next;
    int val;
    ListNode(){}
    ListNode(int val){this.val=val;}
}
class Solution{
    public ListNode deleteSame(ListNode head)
    {
        ListNode dummy=new ListNode(0);
        dummy.next=head;
        ListNode p=head;
        while(p!=null&&p.next!=null)
        {
            if(p.val==p.next.val)
            {
                p.next=p.next.next;
            }else
            {
                p=p.next;
            }
        }
        return dummy.next;
    }
}

删除链表中重复的结点

class Solution{
    public ListNode deleteSame(ListNode head)
    {
        ListNode dummy=new ListNode();
        ListNode p=dummy;
        while(head!=null&&head.next!=null)
        {
            if(head.val!=head.next.val)
            {
                p.next=head;
                p=p.next;
            }
            while(head.next!=null&&head.val==head.next.val)
            {
                head=head.next;
            }
            head=head.next;
        }
        p.next=null;
        return  p;
    }
}

这个就不能原地改了

21. 合并两个有序链表


package org.example;

import java.util.*;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Solution sl=new Solution();
        while(sc.hasNextLine())
        {
            String[]lists=sc.nextLine().split(" ");
            ListNode l1=sl.strToList(lists[0]);
            ListNode l2=sl.strToList(lists[1]);
            ListNode res=sl.mergeTwoLists(l1,l2);
            //......
        }
    }

}
class ListNode{
    ListNode next;
    int val;
    ListNode(){}
    ListNode(int val){this.val=val;}
}
class Solution{
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy=new ListNode(0);
        ListNode p=dummy;
        while(list1!=null&&list2!=null)
        {
            if(list1.val<list2.val)
            {
                p.next=list1;
                list1=list1.next;
            }else
            {
                p.next=list2;
                list2=list2.next;
            }
            p=p.next;
        }
        p.next=list1==null?list2:list1;
        return dummy.next;
    }
    public ListNode strToList(String a)
    {
        ListNode head=new ListNode(a.charAt(0)-'0');
        ListNode p=head;
        for(int i=1;i<a.length();i++)
        {
            p.next=new ListNode(a.charAt(i)-'0');
            p=p.next;
        }
        return  head;
    }
}

912. 手撕归并排序(数组)****

class Solution {
    int []tmp;
    public int[] sortArray(int[] nums) {
        tmp=new int[nums.length];
        mergeSort(nums, 0, nums.length-1);
        return nums;
    }
    public void mergeSort(int[]nums,int l,int r)
    {
        if(l>=r)
        {
            return ;
        }
        int mid=(l+r)>>1;
        mergeSort(nums, l, mid);
        mergeSort(nums, mid+1,r);
        int i=l;
        int j=mid+1;
        int cnt=0;
        while(i<=mid&&j<=r)
        {
            if(nums[i]<=nums[j])
            {
                tmp[cnt++]=nums[i++];
            }else
            {
                tmp[cnt++]=nums[j++];
            }
        }
        while(i<=mid)
        {
            tmp[cnt++]=nums[i++];
        }
        while(j<=r)
        {
            tmp[cnt++]=nums[j++];
        }
        //排序好的部分再放到nums里面
        for(int k=0;k<r-l+1;k++)
        {
            nums[k+l]=tmp[k];
        }
    }
}

链表版的就是先找到中间然后再断开,然后归并,一样的

选取重复频率最高前k个数_求频率最高的前k个数-CSDN博客

有一说一手写堆不会,这里用桶排序的方法吧

19. 删除链表的倒数第 N 个结点

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummy=new ListNode(0);
    dummy.next=head;
    ListNode slow=dummy;
    ListNode fast=head;
    while(n>0)
    {
        fast=fast.next;
        n--;
    }
    while(fast!=null)
    {
        fast=fast.next;
        slow=slow.next;
    }
    slow.next=slow.next.next;
    return dummy.next;
}

5. 最长回文子串

public String longestPalindrome(String s) {
    boolean[][]dp=new boolean[s.length()][s.length()];
    for(int i=0;i<s.length();i++)
    {
        dp[i][i]=true;
    }
    int maxleft=0;
    int maxlen=1;
    for(int j=1;j<dp.length;j++)
    {
        for(int i=0;i<j;i++)
        {
            if(s.charAt(j)!=s.charAt(i))
            {
                dp[i][j]=false;
            }else
            {
                if(j-i<3)
                {
                    dp[i][j]=true;
                }else
                {
                    dp[i][j]=dp[i+1][j-1];
                }
            }
            if(dp[i][j]&&j-i+1>maxlen)
            {
                maxlen=j-i+1;
                maxleft=i;
            }
        }
    }
    return s.substring(maxleft,maxleft+maxlen);
}

442. 数组中重复的数据 - 力扣(LeetCode)

原地哈希

public List<Integer> findDuplicates(int[] nums) {
    List<Integer>res=new ArrayList<>();
    int n=nums.length;
    for(int i=0;i<n;i++)
    {
        int num=nums[i];
        int index=Math.abs(num)-1;//对应的位置
        if(nums[index]>0)
        {
            nums[index]=-nums[index];//表示第一次出现
        }else
        {
            res.add(index+1);//这个位置对应的数出现了两次
        }
    }
    return res;
}

36车 6跑道 没有计时器 最少要几次取前三

答:B、8次 解答:

先分6组 比赛6次,每组取前三 ,得

a1 b1 c1 d1 e1 f1

a2 b2 c2 d2 e2 f2

a3 b3 c3 d3 e3 f3

再每组第一名比一次 ,得

真·第一名 a1 以及 第二名 b1 第三名 c1

d e f 组第一名都上不了前三,所以去掉 d e f

b3<b2<b1<a1,所以 b3 也不要了

c3 <c2< c1< b1< a1, 所以 c3 c2 也不要了

然后再让 b1 c1 b2 a2 a3 去比赛

得出 真·第二名和真·第三名

155. 最小栈

easy

4. 寻找两个正序数组的中位数

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n=nums1.length;
        int m=nums2.length;
        int left=(n+m+1)/2;
        int right=(n+m+2)/2;
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;  

    }
    
    int getKth(int[]nums1,int start1,int end1,int []nums2,int start2,int end2,int k)
    {
        int len1=end1-start1+1;
        int len2=end2-start2+1;
        if(len1>len2)return getKth(nums2, start2, end2, nums1, start1, end1, k);//保证如果有数组空了一定是LEN1
        if(len1==0)return nums2[start2+k-1];
        if(k==1)return Math.min(nums1[start1],nums2[start2]);
        int i=start1+Math.min(len1, k/2)-1;
        int j=start2+Math.min(len2, k/2)-1;
        if(nums1[i]>nums2[j])
        {
            return getKth(nums1, start1, end1, nums2, j+1,end2,k-(j-start2+1));
        }else
        {
            return getKth(nums1, i+1, end1, nums2, start2, end2, k-(i-start1+1));
        }
    }

}

单例模式

class Singleton{
    private volatile static Singleton instance;
    private Singleton(){}
    public static Singleton getInstance()
    {
        if(instance==null)
        {
            synchronized (Singleton.class)
            {
                if(instance==null)
                {
                    instance=new Singleton();
                }
            }
        }
        return  instance;
    }
}

1120. 子树的最大平均值 - 力扣(LeetCode)

class Solution {
    double res=0;
    public double maximumAverageSubtree(TreeNode root) {
        get(root);
        return res;
    }
    int[]get(TreeNode root)
    {
        if(root==null)return new int[]{0,0};
        int[]left=get(root.left);
        int[]right=get(root.right);
        int sum=left[0]+right[0]+root.val;
        int count=left[1]+right[1]+1;
        double avg=1.0*sum/count;
        res=Math.max(avg, res);
        return new int[]{sum,count};
    }
}

144. 二叉树的前序遍历 - 力扣(LeetCode)

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer>res=new ArrayList<>();
    Deque<TreeNode>stk=new LinkedList<>();
    if(root==null)
    {
        return res;
    }
    TreeNode p=root;
    while(!stk.isEmpty()||p!=null)
    {
        while(p!=null)
        {
            res.add(p.val);
            stk.push(p);
            p=p.left;
        }
        p=stk.pop();
        p=p.right;
    }
    return res;
}

压缩字符串abbccc->a1b2c3

LCR 155. 将二叉搜索树转化为排序的双向链表 - 力扣(LeetCode)

简单

*/
class Solution {
    Node pre, head;

    public Node treeToDoublyList(Node root) {
        if(root==null)return null;
        dfs(root);
        head.left=pre;
        pre.right=head;
        return head;
    }

    void dfs(Node cur) {
        if (cur == null)
            return;
        dfs(cur.left);
        if(pre!=null)pre.right=cur;
        else head=cur;
        cur.left=pre;
        pre=cur;
        dfs(cur.right);
    }
}

1044. 最长重复子串 - 力扣(LeetCode)

1262. 可被三整除的最大和 - 力扣(LeetCode)****

这题目难的要死,我选择直接背诵

public int maxSumDivThree(int[] nums) {
    int n=nums.length;
    int[][]f=new int[n+1][3];
    f[0][1]=f[0][2]=Integer.MIN_VALUE;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<3;j++)
        {
            f[i+1][j]=Math.max(f[i][j], f[i][(j+nums[i])%3]+nums[i]);
        }
    }
    return f[n][0];
}

186. 反转字符串中的单词 II - 力扣(LeetCode)

这个你麻痹腾讯问了滴滴也问了

思路就是先字符串整体翻转,再对每个单词翻转

1044. 最长重复子串 - 力扣(LeetCode)

这题直接用hashcode,不用自定义哈希了

面试题 17.15. 最长单词 - 力扣(LeetCode)


  目录