实习凉面经历

记录了2021年在阿里、腾讯、蚂蚁金服、字节跳动等公司实习面试的过程,涉及TCP/IP、数据结构、算法、操作系统、数据库、设计模式等多个技术领域的面试题,包括问题解析与答案,如TCP三次握手、拥塞控制、股票预测动态规划等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做个刷怪记录

2021.3.10 阿里研发岗实习笔试

1. 根据犯人初始位置和一系列指令,判断犯人最终位置。(直接模拟)
2. 一个环形数组,数组长度为3的整数倍。小明从数组中循环抽取数字,每次抽取后数组将删除该位置及其两侧位置的数值。求小明最终能获得的最大数值和。
  leetcode1388题
  问题可以等价转化为:给一个长度为 3n 的环状序列,你可以在其中选择 n 个数,并且任意两个数不能相邻,求这 n 个数的最大值
  解法:动态规划。用 dp[i][j] 表示在前 i 个数中选择了 j 个不相邻的数的最大和。考虑选择当前数或者不选择当前数进行状态转移:
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 2 ] [ j − 1 ] + n u m [ i ] ) dp[i][j]=max(dp[i-1][j],dp[i-2][j-1]+num[i]) dp[i][j]=max(dp[i1][j],dp[i2][j1]+num[i])
   对于循环队列,遍历计算两次dp,第一次去除第一个元素计算(等效不选取第一个元素),第二次去除最后一个元素计算。最终结果为两次 dp 最大值。

2021.3.10 腾讯云研发岗实习初试(凉了)

1. TCP三次握手过程及客户机和服务器的TCP进程状态。

  解答:假设A运行TCP客户进程,B运行TCP服务器进程。

  1. A和B的TCP进程分别创建传输控制模块TCB,且B的服务器进程处于LISTEN(收听)状态
  2. A向B发出连接请求报文,首部中的同步位 SYN=1,选择初始序列号 seq=x,SYN报文不能携带数据,但是要消耗掉一个序号。A的TCP客户进程进入SYN-SENT(同步已发送)状态
  3. B回复确认报文,SYN=1,ACK=1,确认号 ack=x+1。并为自己选择初始序列号 seq=y,该报文不携带数据,同时消耗一个序号。B的TCP服务器进程进入SYN-RCVD(同步收到)状态
  4. A再次回复确认报文,ACK=1,确认号 ack=y+1,序列号seq=x+1。ACK报文可以携带数据,不携带数据则不消耗序列号。此时TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态
  5. B收到A的确认,进入ESTABLISHED状态。

2. TCP报文段表头和IP数据报表头组成。TTL作用。

  • TCP报文段首部:源端口号目的端口号序号使用 m o d ( 2 32 ) mod (2^{32}) mod(232)运算,TCP面向字节流,每一个字节按顺序编号;确认号是期望收到对方下一个报文段的第一个数据字节的序号;数据偏移指本报文数据起始处与本报文开始位置的距离(最大值为15*4=60字节);确认ACK,在建立连接后所有报文的ACK都置1;同步SYN,建立TCP连接时使用;终止FIN,释放连接时使用。窗口是发送方的接收窗口大小;校验和校验伪首部+首部+数据。
  • IP数据报首部:版本首部长度总长度表示首部和数据之和,单位字节;标志用于分片后数据报的组装;标志,MF=1表示还有分片,DF=1表示不能分片;片偏移表示该片在原数据报中的相对位置,以8字节为单位;生存时间TTL防止无法交付的数据报无限制兜圈;协议指明携带的数据使用什么协议;首部校验和,只检验数据报首部不包括数据部分。

3. 什么是拥塞,TCP拥塞控制方法。

  • 拥塞:某段时间内,对网络中的某一资源的需求超过了该资源所能提供的可用部分,导致网络性能变坏。
  • TCP拥塞控制方法:初始时拥塞窗口 cwnd 大小置为1,开始执行慢开始算法,每收到一个确认后,拥塞窗口大小加倍。达到慢开始门限 ssthresh 后,开始执行拥塞避免算法,每收到一个确认后,拥塞窗口大小 + 1。发生超时后, ssthresh = cwnd / 2,cwnd = 1,开始执行慢开始算法。收到3个重复确认后,cwnd = ssthresh = cwnd / 2,开始执行拥塞避免算法。

4. Linux tail指令,如何自己实现访问文件的最后几行。

  • 使用滑动窗口进行查找,当滑动窗口到底时,输出文件内容。
tail [参数] [文件]
-f 循环读取
-c<数目> 显示的字节数
-n<行数> 显示文件的尾部 n 行内容

tail notes.log   //默认显示文件最后10行
tail -n +20 notes.log  //显示第20行至文件末尾

5. 快排实现。

  • 基本思想:随机找出一个数,可以随机取,也可以取固定位置,一般是取第一个或最后一个称为基准,然后就是比基准小的放在左边,比基准大的放到右边。如何放呢?就是和基准进行交换,这样交换完左边都是比基准小的,右边都是比较基准大的,这样就将一个数组分成了两个子数组,然后再按照同样的方法把子数组再分成更小的子数组,直到不能分解为止。
  • python实现
def QuickSort(nums:list, left:int, right:int):
    if left < right:
        position = findPosition(nums, left, right)
        QuickSort(nums, left, position-1)
        QuickSort(nums, position+1, right)

def findPosition(nums:list, leftIndex:int, rightIndex:int):
    '''寻找基准位置'''
    initNum = nums[leftIndex]
    left = leftIndex
    right = rightIndex
    while (left < right):
        while(left < right and nums[right] > initNum):
            right -= 1
        while(left < right and nums[left] <= initNum):
            left += 1
        if left != right:
            swap(nums, left, right)
    swap(nums, left, leftIndex)
    return left

def swap(nums:list, left:int, right:int):
    '''交换两位置元素'''
    temp = nums[left]
    nums[left] = nums[right]
    nums[right] = temp
        
if __name__ == "__main__":
    a = [1, 5, 7, 2, 6, 3, 9, 4]
    QuickSort(a, 0, len(a)-1)
    print(a)
  • Java实现
import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int[] a = {1, 4, 2, 6, 8, 4, 5, 7};
        quickSort(a, 0, a.length-1);
        System.out.println(Arrays.toString(a));
    }

    public static void quickSort(int[] array, int left, int right) {
        if (left < right) {
            int position = searchPosition(array, left, right);
            quickSort(array, left, position-1);
            quickSort(array, position+1, right);
        }
    }

    public static int searchPosition(int[] array, int leftIndex, int rightIndex) {
        int initNum = array[leftIndex];
        int left = leftIndex;
        int right = rightIndex;
        while (left != right) {
            while(left < right && array[right] > initNum) {
                right--;
            }
            while(left < right && array[left] <= initNum) {
                left++;
            }
            if(left < right) {
                swap(array, left, right);
            }
        }
        swap(array, leftIndex, left);
        return left;
    }

    public static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    } 
}

6. 你知道哪些常见的设计模式

  • 工厂模式
    通过一个工厂类来创建实现某个接口的所有子类,工厂模式使其创建过程延迟到子类进行。在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
    优点:(1)一个调用者想创建一个对象,只要知道其名称,通过工厂类来创建就可以了。 (2)扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 (3)屏蔽产品的具体实现,调用者只关心产品的接口。
    缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
  • 单例模式
    这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。保证一个类仅有一个实例,并提供一个访问它的全局访问点。
    单例模式有三种实现方式:(1)懒汉式,线程不安全(2)饿汉式
  • 代理模式
    一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们增加中间层,创建具有现有对象的对象,以便向外界提供功能接口。为其他对象提供一种代理以控制对这个对象的访问。
  • MVC模式(不属于23中设计模式)
    Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
    (1)Model(模型):模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
    (2)View(视图):视图代表模型包含的数据的可视化。
    (3)Controller(控制器):控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

2021.3.10 腾讯调剂岗面试(凉了)

1. 股票预测:输入一个列表 p r i c e s prices prices p r i c e s [ i ] prices[i] prices[i]表示 i i i 天的股票价格,你可以选择一天买入,并在另一天卖出,求最大利润。
  典型动态规划题目, d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示手里有股票时最大利润; d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示手里没有股票时最大利润。状态转移方程
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , − p r i c e s [ i ] ) d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 0 ] + p r i c e s [ i ] , d p [ i − 1 ] [ 1 ] ) dp[i][0]=max(dp[i-1][0], -prices[i])\\ dp[i][1]=max(dp[i-1][0]+prices[i],dp[i-1][1]) dp[i][0]=max(dp[i1][0],prices[i])dp[i][1]=max(dp[i1][0]+prices[i],dp[i1][1])

'''
dp[i][0]表示手里有股票时最大利润
dp[i][1]表示手里没有股票时最大利润
'''
def maxPrices(prices: list):
	dp = [[0, 0] for i in range(len(prices))]
	dp[0] = [-prices[0], 0]
	for i in range(1, len(prices)):
		dp[i][0] = max(dp[i-1][0], -prices[i])
		dp[i][1] = max(dp[i-1][0] + prices[i], dp[i-1][1])
	return dp[-1][1]

2. 给定一个链表,将链表的倒数第k个节点移动到链表头部
  题目挺简单,但面试官要求使用C语言写,尝试了一下,结构体内容忘完了,最后只给他说了思路。
  使用快慢指针,快指针首先移动k个节点,然后慢指针从头部开始和快指针同时移动,快指针到达链表结尾时慢指针刚好指向倒数第k个节点,随后对头节点和该节点交换。下面给出python版本。

class Node:
    def __init__(self, val, nextNode=None):
        self.val = val
        self.next = nextNode

def changeNode(headNode, k: list):
    left = headNode
    right = headNode
    for i in range(k+1):
        right = right.next
    while right:
        left = left.next
        right = right.next
    lastNode = left        # 倒数第K+1个节点
    KNode = left.next      # 倒数第K个节点
    nextNode = KNode.next  # 倒数第K-1个节点

    KNode.next = headNode.next
    lastNode.next = headNode
    headNode.next = nextNode
    return KNode

3. TCP四次挥手过程,TCP客户进程为什么要等待 2MSL 时间

  • A,B初始都处于 ESTABLESHED (连接建立)状态
  • A的TCP客户进程发出连接释放报文,终止控制位 FIN = 1,seq = u,随后A进入 FIN-WAIT-1(终止等待)状态;FIN报文不携带数据,也要消耗一个序号。
  • B回复确认报文,ACK=1,确认号 ack = u + 1, seq = v,TCP连接处理半关闭状态,B仍可以向A发生数据,B进入 CLOSE-WAIT(关闭等待)状态。
  • A 收到 B 的确认后,不做任何回复,仍然处于终止等待状态。
  • B若不发送数据,则发送连接释放报文,FIN = 1,seq = v+k,ack = u + 1,随后B进入 LAST-ACK(最后确认)状态
  • A回复确认报文,ACK=1,seq = u + 1,ack = v+k+1,然后进入TIME-WAIT(时间等待)状态
  • 时间等待状态需要等待 2MSL(最长报文段寿命)时间。(1)为了保证A发送的最后一个ACK报文段能够到达B,若B没收到ACK报文,会进行超时重传 FIN+ACK报文。(2)保证本次连接中所产生的报文都从网络消失,保证下次连接不会出现这次连接中的报文。

4. TCP和UDP区别,TCP如何实现可靠数据传输

  • TCP面向连接,UDP无连接
  • TCP可靠性传输实现:TCP连接双方同时维护发送窗口和接收窗口,两方相对的窗口大小一致(可能因为拥塞控制更小),发送窗口只有在收到确认时才向前移动,若超时未收到确认则重传整个窗口的数据;接收方只对按序收到的数据的最大序号回复确认,并且采用累积确认的方式(可以屯一点字节流,在合适的时候发送确认)。
  • TCP重传时间的选择:当报文发生重传时,超时重传时间RTO记为原来的2倍,否则按以下公式计算, α = 0.125 \alpha=0.125 α=0.125 β = 0.25 \beta=0.25 β=0.25
    R T T S = ( 1 − α ) × R T T S + α × R T T R T T D = ( 1 − β ) × R T T D + β × ∣ R T T S − R T T ∣ R T O = R T T S + 4 × R T T D RTT_S=(1-\alpha)\times RTT_S+\alpha \times RTT \\ RTT_D=(1-\beta)\times RTT_D+\beta \times |RTT_S-RTT| \\ RTO = RTT_S +4\times RTT_D RTTS=(1α)×RTTS+α×RTTRTTD=(1β)×RTTD+β×RTTSRTTRTO=RTTS+4×RTTD

5. 你会使用多线程吗

  • 不会

2021.3.17 蚂蚁金服开发岗

1. 表A有user_id,user_province,join_date三个字段,表B里面有user_id,use_time,use_date三个字段。基于两张表计算每个省的最近一个月加入用户的使用总时长的平均值。

SELECT AVG(B1.total_time)
FROM (  -- 根据表B计算每个用户一个月内的使用总量
	SELECT user_id, SUM(use_time) as total_time
	FROM B
	WHERE DATE_SUB(CURDATE(), INTERVAL 1 MONTH) < use_date 
	GROUP user_id) B1 
	INNER JOIN A ON A.user_id = B1.user_id
GROUP BY A.user_province; 

2. 现有2个链表,链表节点是double型数据,都已按照升序排序。请将这2个链表按升序合并成1个新的有序链表。

public class Node {
	public int value;
	public Node next;

	public Node(int value) {
		this.data = value;
	}
}

class MyList {
    public static Node merge(Node list1, Node list2) {
        if (list1 == null || list2 == null) {
            return list1 != null ? list2 : list1;
        }
        Node node1 = list1;
        Node node2 = list2;
        Node head;
        if (node1.value > node2.value){  // 选取头节点, 返回节点
            head = node2;
            node2 = node2.next;
        } else {
            head = node1;
            node1 = node1.next;
        }
        Node temp = head;
    
        while (node1 != null && node2 != null) { // 合并两个链表   
            if (node1.value > node2.value) {
                temp.next = node2;
                node2 = node2.next;
            } else {
                temp.next = node1;
                node1 = node1.next;
            }
            temp = temp.next;
        }
        temp.next = node1 == null ? node2 : node1;
        return head;
    }
}

2021.3.21 字节开发岗笔试(凉了)

两个小时,四道编程题
1. 一群猴子排队取食香蕉,每只猴子最多不会拿超过 自身食量2倍 或 当前还存在的香蕉的一半,最后一只猴子可拿下全部香蕉。问最少需要多少香蕉才能保证所有猴子都吃饱。
输入:数组monkey,monkey[ i ]表示第 i 个猴子的需要的香蕉数。

2. 有N块蛋糕,每块蛋糕有个美味度,求李华连续取不超过M块蛋糕的最大美味度和。输入:数组 A,A[ i ]表示第 i 块蛋糕的美味度;整数 M

3. 将一个空文本通过重复以下三种操作,求变成N个相同字符所需要消耗的最小时间。
 操作1:将现有文本字符翻倍,消耗A个时间
 操作2:在文本末尾添加一个字符,消耗B个时间
 操作3:将文本末尾字符删除,消耗B个时间
输入:整数 N;整数 A;整数 B

4. 给定两个字符串 S 和 T 和整数 K,其中 T 的长度为2。现最多可以将字符串 S 改动 K 次(每次改动为替换某个位置的字符),使 S 中含有的子序列等于 T 的数量最大,求这个最大数量。
输入:字符串 S,字符串 T,整数 K

2021.3.21 腾讯开发岗笔试

不想写

2021.3.22 腾讯安全部门开发岗面试

1. 聊项目

2. Java垃圾回收机制

  • 判断垃圾
    (1)引用计数法:给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已“死”。
    (2)可达性分析算法:通过一系列称为 GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到 GC Roots 没有任何的引用链相连时(从 GC Roots 到这个对象不可达)时,证明此对象不可用。在Java语言中,可作为GC Roots的对象包含以下几种:虚拟机栈(栈帧中的本地变量表)中引用的对象;方法区中静态属性引用的对象;方法区中常量引用的对象;本地方法栈中(Native方法)引用的对象。
  • 垃圾回收算法
    (1)标记清除法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。该方法效率低,易产生内存碎片。
    (2)复制算法:它将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。
    (3)标记整理算法:针对老年代的特点。标记过程仍与标记-清除过程一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象向一端移动,然后直接清理掉端边界以外的内存。
  • 内存模型与回收策略
    Java堆分为新生代和老年代。在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法(Minor GC);而老年代中对象存活率高、没有额外空间对它进行分配担保,就必须采用"标记-清理"或者"标记-整理"算法(Full GC)。

3. SQL优化
不知道

4. HashMap底层实现
在HashMap中每个节点封装为一个Node<K,V>的内部类,用一个数组来存储单向链表,一个单向链表上节点中K的hashcode相同。如果哈希表单向链表中元素超过8个,那么单向链表这种数据结构会变成红黑树数据结构。当红黑树上的节点数量小于6个,会重新把红黑树变成单向链表数据结构。

5. TCP协议头构成,TIME_WAIT发生在什么阶段,为什么要等2MSL。
TIME_WAIT发生在TCP释放连接过程中,客服端确认接收服务器释放请求后的阶段。

6. TCP拥塞控制方法,什么时候执行指数退避算法。
载波监听多路访问/碰撞检测CSMA/CD协议中使用指数退避算法。在检测到信道发生碰撞后,立即停止发送数据,并发送人为干扰信号来强化碰撞,此时执行指数退避算法,等待 r r r 倍512比特时间(51.2μs),重传超过16次则向上报错。
最 小 帧 长 L m i n / 网 络 带 宽 R = R T T m a x ≥ 2 ∗ 最 大 距 离 d m a x / 信 号 传 播 速 度 V 效 率 = 1 1 + 5 t p r o p / t t r a n s , t p r o p 为 两 节 点 最 大 传 输 延 迟 , t t r a n s 为 最 长 帧 传 输 延 迟 最小帧长L_{min}/网络带宽R=RTT_{max}≥2*最大距离d_{max}/信号传播速度V\\ 效率=\frac{1}{1+5t_{prop}/t_{trans}},t_{prop}为两节点最大传输延迟,t_{trans}为最长帧传输延迟 Lmin/R=RTTmax2dmax/V=1+5tprop/ttrans1tpropttrans

  • 截断二进制指数退避:从离散的整数集合 [ 0 , 1 , … , ( 2 k − 1 ) ] [0,1,…,(2^k-1)] [0,1,,(2k1)]中随机选取一个数 r r r,重传推迟 r r r 倍争用期。 k = M i n ( 重 传 次 数 , 10 ) k=Min(重传次数,10) k=Min(10)

7. 进程间通信方式

  • 管道:一种半双工的通信方式,数据只能单向流动,而且只能在具有父子关系的进程间使用。
  • 消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
  • 共享存储:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
  • 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。
  • 套接字:用于不同机器间的进程通信

8. 算法题:将循环数组的每个位置向后移动K个位置,使用三种方式原地实现。

  • 方法一:将原数组copy,在新数组中取元素在原数组中修改。时间复杂度O(n),空间复杂度O(n)。
  • 方法二:新建一个长度为K的队列,保存被覆盖的 K 个元素。时间复杂度O(n),空间复杂度O(k)
  • 方法三:每次遍历数组向后移动1个位置,遍历K次数组,每次遍历只需1个临时变量保存覆盖元素。时间复杂度O(nk),空间复杂度O(1)。

9. 智力题:64匹马和8个赛道,每次比赛只能得到马的快慢次序,需要多少次比赛才能找出最快的4匹马

  • 将所有🐎分为8组,进行8次比赛。
  • 将每组的冠军提取出来进行1次比赛。可以获得第一名。
  • 将后四名🐎所在的组全部剔除,将前四名🐎所在组的一二名一起比赛。

2021.3.31 蚂蚁金服二面

1. 聊项目

2. HashMap和TreeMap的区别

  • HashMap:底层数组+列表+红黑树;Key 和 Value 都可以为 null
  • TreeMap:底层红黑树;Key 不能为 null , Value 可以为 null,

3. MySQL底层使用的是什么数据结构存储数据
MyISAM和InnoDB两种存储引擎都采用了B+树的数据结构

4. 垃圾回收机制

5. 算法题:给一个数字序列,求它的下一排列,例:1,3,5,7,9 -> 1,3,5,9,7

  • 首先从后向前查找第一个顺序对 ( i , i + 1 ) (i,i+1) (i,i+1),满足 a [ i ] < a [ i + 1 ] a[i] < a[i+1] a[i]<a[i+1]。此时 [ i + 1 , n ) [i+1,n) [i+1,n) 必然是下降序列。

  • 如果找到了顺序对,那么在区间 [ i + 1 , n ) [i+1,n) [i+1,n) 中从后向前查找第一个元素 j j j 满足 a [ i ] < a [ j ] a[i] < a[j] a[i]<a[j]

  • 交换 a [ i ] a[i] a[i] a [ j ] a[j] a[j],此时可以证明区间 [ i + 1 , n ) [i+1,n) [i+1,n) 必为降序。可以直接使用双指针反转区间 [ i + 1 , n ) [i+1,n) [i+1,n) 使其变为升序,而无需对该区间进行排序。

def nextPermutation(nums):
    i = len(nums) - 2
    while i >= 0 and nums[i] >= nums[i + 1]:
        i -= 1
    if i >= 0:
        j = len(nums) - 1
        while j >= 0 and nums[i] >= nums[j]:
            j -= 1
        nums[i], nums[j] = nums[j], nums[i]
        
    left, right = i + 1, len(nums) - 1
    while left < right:
        nums[left], nums[right] = nums[right], nums[left]
        left += 1
        right -= 1

2021.4.9 美团初试

1. 自我介绍

2. HashMap的底层实现,插入一个键值对的过程。

3. “==” 和 equals() 的区别,两种方法判断 Integer 类型结果相同吗?
定义的Integer在-128~127之间时,Integer的 == 和 equal() 返回是一样的,但当Integer 在那个范围之外时,equal 比较的是值,两值相等就返回true,== 则比较的是地址。如果 Integer 和 int 类型比较则会执行拆箱的过程。

4. 用过哪些数据库引擎,使用的什么索引结构,B树和B+树的区别

5. TCP和UDP的区别,什么场景下使用,有哪些应用层协议使用TCP。

6. Linux上部署的Java程序CPU占用很高,怎么处理?

7. 如何用Linux指令在一个网络日志文件中查找出现次数最多的5个ip

8. Spring中AOP的实现方式,有什么区别。

  • JDK动态代理实现:底层使用反射机制实现动态代理。
  • CGLIB动态代理实现:通过继承方式实现动态代理,要求某个类不能被标记为 final。

9. 算法题:给定一个字符串,找出不含重复字母的最长子串。
滑动窗口实现。

2021.4.14 华为笔试

1. 输入字符串,字符串中含有字母和小括号,被小括号括起来的子串需要逆序,输出去除括号的字符串

2. 模拟题

3. 给定一个数组nums,nums[i]表示从i位置能跳跃的最大距离,返回从数组首位到数组末位最少需要跳几次。

2021.4.18 网易笔试

1. 输入字符串,只含有小括号,中括号,大括号。若字符串中所有括号均能配对成功则为合法字符串,每配对成功一个小括号得分加1,配对成功一个中括号得分加2,配对成功一个大括号得分加3,若字符串合法返回得分总和,否则返回-1
例:"{()[{}]}",返回9;"{[(])()}",返回-1
解法:维护一个栈

2. 给定一个N×2的矩阵matrix,和一个长度为M的数组numList;其中matrix[i]表示一个区间,针对numList中的每个元素numList[j],找出所有i满足matrix[i][0]<=numList[j]<=matrix[i][1]。
例:输入nums1 = [[1000,12123],[1232,32121],[1111,3232]],nums2=[1000,1333,900];返回[[1],[1,2,3],[0]]
tips:O(n^2)的暴力解法超时,不能通过全部用例

3. 给定一个数组,对于其任意子数组,该子数组的得分为(该子数组所有奇数位的和) 减去(该子数组所有偶数位的和),找出得分最大的子数组,并返回该得分。
解法:暴力解法枚举所有子数组计算最大得分会超时,采用动态规划从后向前遍历

def(numList):
	N = len(numList)
	if N == 1:
    	return max(numList[0], ret)
    	
    # dp[i][0] 表示以 i 为起点的最大和
    # dp[i][1] 表示以 i 为起点的最小和
    # dp[i][0] = max(-dp[i+1][1] + nums[i], 0)
    # dp[i][1] = min(-dp[i+1][0] + nums[i], 0)
    
    dp = [[0, 0] for _ in range(N)]
    dp[N-1] = [max(numList[N-1], 0), min(numList[N-1], 0)]
    ret = dp[N-1][0]
    for i in range(N-2, -1, -1):
        dp[i][0] = max(-dp[i+1][1] + numList[i], 0)
        dp[i][1] = min(-dp[i+1][0] + numList[i], 0)
        ret = max(ret, dp[i][0])
    return ret
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值