其他分享
首页 > 其他分享> > 叮~~您有一份腾讯面经资料(儿童节福利)!请查收!(部分解析)

叮~~您有一份腾讯面经资料(儿童节福利)!请查收!(部分解析)

作者:互联网

六月开始啦!在这艳阳高照的儿童节,整理了一些腾讯面试的试题。希望能对大家有帮助!(haha)

在这里插入图片描述

首先是WeChat事业群

微信事业群

实例1

一面

1、上来四个题目
(1)两个用链表表示的数字相加,用链表返回结果,如9->1>2和6->1->8,即912+618,返回1->5->3->0
(2)判断一棵树是否为平衡二叉树

平衡二叉树是递归定义的,同样解法也用递归

bool IsBalanced(BTree root)
{
  if(root == NULL) return true;
 int ldepth = Depth(root->lchild);
 int rdepth = Depth(root->rchild);
 
 if(abs(ldepth-rdepth)>1)return false;
 
  return IsBanlanced(root->lchild)&&IsBanlanced(root->rchild);
}

(3)旋转数组找最小值

>/**
	假设按照升序排序的数组在预先未知的某个点上进行了旋转。
	( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
	请找出其中最小的元素。
	你可以假设数组中不存在重复元素。
 */
public class 寻找旋转排序数组中的最小值 {
	public static void main(String[] args) {
		int[] a = {2,1};
		System.out.println(findMin(a));
	}
	/**
	 * 思路:很显然的对于中间元素 a[mid]>a[L]则a[L...mid]有序,否则右边有序,对于有序的部分
	 * 我们能够直接得到在该有序段落中的最小值(为a[L]或者a[mid]),至此,我们对于费有序段落继续使用相同的
	 * 求解方式即可得到结果
	 */
	public static int findMin(int[] a) {
		int L = 0;
		int R = a.length-1;
		int ans = 1000;
		while(L<=R) {
			int mid = (L+R)/2;
			if(a[mid]>=a[L]) {//左侧有序
				ans = Math.min(ans, a[L]);
				L = mid+1;
			}else {//右侧有序
				ans = Math.min(ans, a[mid]);
				R = mid-1;
			}
		}
		return ans;
    }
}

(4)最大的连续子数组的和

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        int cur = 0;
        int max = Integer.MIN_VALUE;
        for(int i = 0 ;i<array.length ; i++){
            cur += array[i];
            max = Math.max(max, cur);
            cur = (cur<0)? 0:cur;
        }
        return max;
    }
}

花了35分钟,给面试官讲思路,面试官问有没有可以优化的地方,又花了10分钟做优化

2、问项目(大约30分钟)
3、讲一下三次握手的过程,为什么不能两次?
4、僵尸进程是什么,出现僵尸进程怎么办?

僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被init接管,子进程退出后init会回收其占用的相关资源。
通俗的可以这么说:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程。

  • 方法一:父进程回收法
    wait函数将使其调用者阻塞,直到其某个子进程终止。故父进程可调用wait函数回收其僵尸子进程。除此之外,waitpid函数提供更为详尽的功能( 增加了非阻塞功能以及指定等待功能 )。
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int pid;
    int *status;

    printf("%s\n", "启动父进程");

    if ((pid = fork()) < 0) {
        printf("%s\n", "创建子进程失败");
        exit(1);
    }
    else
        if (pid ==0) {
            printf("%s\n", "进入子进程");
            sleep(4);
            // 终止子进程
            exit(0);
        }
    else {
        // 进入父进程
        // 回收僵尸子子进程
        wait(status);
        printf("%s\n", "回收完毕");
    }

    exit(0);
}
  • 方法二:init进程回收法
    上面的这种解决方案需要父进程去等待子进程,但在很多情况下,这并不合适,因为父进程也许还有其他任务要做,不能阻塞在这里。在讲述下面这种不用父进程等待就能完成回收子进程的方法之前,先请明白以下两个概念:
    1、如果父进程先于子进程结束,那么子进程的父进程自动改为 init 进程。
    2、如果 init 的子进程结束,则 init 进程会自动回收其子进程的资源而不是让它变成僵尸进程。
#include "apue.h"
#include <sys/wait.h>

int
main(void)
{
    pid_t    pid;

    if ((pid = fork()) < 0) {    // 创建第一个子进程
        err_sys("fork error");
    } else if (pid == 0) {    // 进入第一个子进程
        if ((pid = fork()) < 0)    // 创建第二个子进程
            err_sys("fork error");
        else if (pid > 0) // 进入第一个子进程
            exit(0);    // 终止第一个子进程
        // 第二个子进程在睡眠2S后才执行,这样一般情况下第一个子进程会先终止。
        sleep(2);
        // 这时,第一个子进程肯定终止了,那么它的父进程就自动变成了init。
        printf("second child, parent pid = %d\n", getppid());
        exit(0);
    }

    // 父进程等待并回收第一个子进程
    if (waitpid(pid, NULL, 0) != pid)
        err_sys("waitpid error");

    // 父进程执行到这里以后,可以退出,也可以执行其他的任务。
    // 对于刚才那第二个子进程,它继承了父进程的资源,同时它终止后也会被init进程回收,
    // 不会成为僵尸进程。
    exit(0);
}

说明:

  1. fork创建子进程以后,子进程拥有的是父进程的一个资源副本,而不是和它共享资源。
  2. 子进程终止后变成僵尸进程并不是系统BUG,而是因为子进程终止后,其一些信息操作系统或者用户以后还可能会用到。

5、有什么想问的

此时已经面试1小时20分,一面到此为止。好好准备二面。

二面

1、介绍项目(30分钟)
2、数组类型和指针类型有什么区别?数组名占空间吗?
3、什么时候调用拷贝构造函数
4、类中的const成员函数一般用在什么场合
5、场景题。一张100万x100万的图像,一条曲线围城一个闭合区域,给一堆点,怎么判断这些点在不在这个闭合区域内?( 注意这里内存很小,不能把整张图片加载到内存。)
6、场景题。两块广告牌,五个广告商,设计一个算法,在一段时间内五个广告商的广告出现次数为1:2:3:4:5,注意两个广告牌不能同时播同一个广告。
7、做题(速度越快越好)
(1)设计一个不考虑大小写的字符串比较函数
(2)旋转数组找最小值(和一面重复了)
(3)二叉树,每个节点值都不一样,给三个值a,b,c(不是指针,是节点值),找到他们的最小公共祖先

3个题都做出来了。花了约35分钟。

这篇文章主要是分享给有面试需求的朋友们。我整理了多家互联网大厂的多年面试题,多位大佬的面经资料,以及Java学习资料。有需要的朋友可以点击进入获取。暗号:CSDN。

实例2

1、自我介绍
2、你了解什么缓存呢
3、Redis
4、缓存雪崩如何解决?

这里可以去参考另一篇文章的第19点

点这个——>指路链接

5、你还知道什么缓存?
6、CDN具体实现步骤
7、DNS具体的解析,使用到什么缓存?使用到什么协议?
8、UDP, TCP区别

在比较这两者之前,有必要先了解一下TCP/IP模型,有助于我们理解后续的内容
(1)TCP/IP网络模型
计算机与网络设备要相互通信,双方就必须基于相同的方法。比如,如何探测到通信目标、由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定。不同的硬件、操作系统之间的通信,所有的这一切都需要一种规则。而我们就把这种规则称为协议(protocol)。
TCP/IP 是互联网相关的各类协议族的总称,比如:TCP,UDP,IP,FTP,HTTP,ICMP,SMTP 等都属于 TCP/IP 族内的协议。
TCP/IP模型是互联网的基础,它是一系列网络协议的总称。这些协议可以划分为四层,分别为链路层(网络接口层)、网络层、传输层和应用层。

  • 链路层(网络接口层):负责封装和解封装IP报文,发送和接受ARP/RARP报文等。
  • 网络层:负责路由以及把分组报文发送给目标网络或主机。
  • 传输层:负责对报文进行分组和重组,并以TCP或UDP协议格式封装报文。
  • 应用层:负责向用户提供应用程序,比如HTTP、FTP、Telnet、DNS、SMTP等。

(2)UDP
UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。


它有以下几个特点:
①面向无连接
首先 UDP 是不需要和 TCP一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了。并且也只是数据报文的搬运工,不会对数据报文进行任何拆分和拼接操作。

具体来说就是:

  • 在发送端,应用层将数据传递给传输层的 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
  • 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报文头就传递给应用层,不会任何拼接操作

②有单播,多播,广播功能
UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能。
③UDP是面向报文的
发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。因此,应用程序必须选择合适大小的报文
④不可靠性
首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。
并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。
概括来说,UDP只会把想发的数据报文一股脑的丢给对方,并不在意数据有无安全完整到达。

⑤头部开销小,传输数据报文时是很高效的

UDP 头部包含了以下几个数据:

  • 两个十六位的端口号,分别为源端口(可选字段)和目标端口
  • 整个数据报文的长度
  • 整个数据报文的检验和(IPv4 可选 字段),该字段用于发现头部信息和数据中的错误
    因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的

(3)TCP
当一台计算机想要与另一台计算机通讯时,两台计算机之间的通信需要畅通且可靠,这样才能保证正确收发数据。例如,当你想查看网页或查看电子邮件时,希望完整且按顺序查看网页,而不丢失任何内容。当你下载文件时,希望获得的是完整的文件,而不仅仅是文件的一部分,因为如果数据丢失或乱序,都不是你希望得到的结果,于是就用到了TCP。

TCP协议全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的RFC 793定义。TCP 是面向连接的、可靠的流协议。流就是指不间断的数据结构,你可以把它想象成排水管中的水流。

①TCP连接过程
如下图所示,可以看到建立一个TCP连接的过程为(三次握手的过程):


第一次握手
客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。
第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。
第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。
这里可能大家会有个疑惑:为什么 TCP 建立连接需要三次握手,而不是两次?这是因为这是为了防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误。
在这里插入图片描述
②TCP断开连接

TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK。
第一次挥手
若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。
第二次挥手
B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。
第三次挥手
B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。
第四次挥手
A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。
③TCP协议的特点

  • 面向连接
    面向连接,是指发送数据之前必须在两端建立连接。建立连接的方法是“三次握手”,这样能建立可靠的连接。建立连接,是为数据的可靠传输打下了基础。
  • 仅支持单播传输
    每条TCP传输连接只能有两个端点,只能进行点对点的数据传输,不支持多播和广播传输方式。
  • 面向字节流
    TCP不像UDP一样那样一个个报文独立地传输,而是在不保留报文边界的情况下以字节流方式进行传输。
  • 可靠传输
    对于可靠传输,判断丢包,误码靠的是TCP的段编号以及确认号。TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
  • 提供拥塞控制
    当网络出现拥塞的时候,TCP能够减小向网络注入数据的速率和数量,缓解拥塞
  • TCP提供全双工通信
    TCP允许通信双方的应用程序在任何时候都能发送数据,因为TCP连接的两端都设有缓存,用来临时存放双向通信的数据。当然,TCP可以立即发送一个数据段,也可以缓存一段时间以便一次发送更多的数据段(最大的数据段大小取决于MSS)。

(4)TCP和UDP的比较
①对比

②总结

  • TCP向上层提供面向连接的可靠服务 ,UDP向上层提供无连接不可靠服务。
  • 虽然 UDP 并没有 TCP 传输来的准确,但是也能在很多实时性要求高的地方有所作为
  • 对数据准确性要求高,速度可以相对较慢的,可以选用TCP

9、TCP三次握手详细

可以参考另一篇文章的第23点的第(4)小点的第③小点

点这里——>指路链接

10、常见的TCP攻击(半连接,全连接),如何解决
11、webSocket,原理?怎么实现长连接?
12、是http的keep-alive还是wenSocket的keep-alive?他们有什么区别?
13、keep-alive实现有了解吗?
14、select和epoll的演化过程,区别,为什么会出现epoll?
15、epoll是怎么是实现的?
16、实习期间干嘛了/
17、做题:思维10个海盗

还有些问题记不太清了。。。。

然后是腾讯Java工程师的

腾讯Java 工程师

实例1

一面

1、mysql索引结构?
2、redis持久化策略?

(1)RDB:快照形式是直接把内存中的数据保存到一个dump的文件中,定时保存,保存策略。当Redis需要做持久化时,Redis会fork一个子进程,子进程将数据写到磁盘上一个临时RDB文件中。当子进程完成写临时文件后,将原来的RDB替换掉。
(2)AOF:把所有的对Redis的服务器进行修改的命令都存到一个文件里,命令的集合。使用AOF做持久化,每一个写命令都通过write函数追加到appendonly.aof中。aof的默认策略是每秒钟fsync一次,在这种配置下,就算发生故障停机,也最多丢失一秒钟的数据。缺点是对于相同的数据集来说,AOF的文件体积通常要大于RDB文件的体积。根据所使用的fsync策略,AOF的速度可能会慢于RDB。Redis默认是快照RDB的持久化方式。

3、zookeeper节点类型说一下?
4、zookeeper选举机制?

(1)半数机制(paxos协议)
集群中半数以上机器存活,集群可用,所以Zookeeper适合安装奇数台服务器
(2)内部选举
在分布式系统中选主最直接的方法是直接选定集群的一个节点为leader,其它的节点为follower,这样引入的一个问题是如果leader节点挂掉,整个集群就挂掉了。需要有一种算法自动选主,如果leader节点挂掉,则从follower节点中选出一个主节点。
①选举阶段( Leader election)
最大ZXID也就是节点本地的最新事务编号,包含epoch和计数两部分。epoch是纪元的意思,相当于Raft算法选主时候的term,标识当前leader周期,每次选举一个新的Leader服务器后,会生成一个新的epoch

  • 所有节点处于Looking状态,各自依次发起投票,投票包含自己的服务器ID和最新事务ID(ZXID)。
  • 如果发现别人的ZXID比自己大,也就是数据比自己新,那么就重新发起投票,投票给目前已知最大的ZXID所属节点。
  • 每次投票后,服务器都会统计投票数量,判断是否有某个节点得到半数以上的投票。如果存在这样的节点,该节点将会成为准Leader,状态变为Leading。其他节点的状态变为Following。

②发现阶段(Discovery)

  • 为了防止某些意外情况,比如因网络原因在上一阶段产生多个Leader的情况。
  • Leader集思广益,接收所有Follower发来各自的最新epoch值。Leader从中选出最大的epoch,基于此值加1,生成新的epoch分发给各个Follower。
  • 各个Follower收到全新的epoch后,返回ACK给Leader,带上各自最大的ZXID和历史事务日志。Leader选出最大的ZXID,并更新自身历史日志。

③同步阶段( Synchronization)
Leader刚才收集得到的最新历史事务日志,同步给集群中所有的Follower。只有当半数Follower同步成功,这个准Leader才能成为正式的Leader。

5、zookeeper主节点故障,如何重新选举?
6、syn机制?
7、线程池的核心参数;
8、threadlocal的实现,原理,业务用来做什么?
9、spring di的原理;
10、四次挥手;

可以参考另一篇文章的第23点的第(4)小点的第③小点

点这里——>指路链接

11、gcroot选择;
12、标记清除算法的过程,标记清楚算法如何给对象分配内存空间?
13、cms算法的缺点;

二面

1、correnthashmap?
2、threadlocal原理?
3、hashmap;
4、Java数据类型,同步机制;
5、讲讲贪心算法;

(1)基本概念
所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)
所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。

(2)贪心算法的基本思路

  • 建立数学模型来描述问题
  • 把求解的问题分成若干个子问题
  • 对每个子问题求解,得到子问题的局部最优解
  • 把子问题的解局部最优解合成原来问题的一个解

(3)存在的问题

  • 不能保证求得的最后解是最佳的
  • 不能用来求最大值或最小值的问题
  • 只能求满足某些约束条件的可行解的范围

(4)适用的问题
贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。

(5)贪心选择机制
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。

(6)贪心算法的实现框架
从问题的某一初始解出发:
while (朝给定总目标前进一步)
{
利用可行的决策,求出可行解的一个解元素。
}
由所有解元素组合成问题的一个可行解;

(7)例题分析
【背包问题】有一个背包,容量是M=150,有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
物品:A B C D E F G
重量:35 30 60 50 40 10 25
价值:10 40 30 50 35 40 30
分析:
目标函数: ∑pi最大
约束条件是装入的物品总质量不超过背包容量:∑wi<=M( M=150)
(1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?
(2)每次挑选所占重量最小的物品装入是否能得到最优解?
(3)每次选取单位重量价值最大的物品,成为解本题的策略
值得注意的是,贪心算法并不是完全不可以使用,贪心策略一旦经过证明成立后,它就是一种高效的算法。比如,求最小生成树的Prim算法和Kruskal算法都是漂亮的贪心算法。
贪心算法还是很常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。
可惜的是,它需要证明后才能真正运用到题目的算法中。
一般来说,贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。
对于例题中的3种贪心策略,都是无法成立(无法被证明)的,解释如下:
①贪心策略:选取价值最大者。反例:
W=30
物品:A B C
重量:28 12 12
价值:30 20 20
根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。
②贪心策略:选取重量最小。它的反例与第一种策略的反例差不多。
③贪心策略:选取单位重量价值最大的物品。反例:
W=30
物品:A B C
重量:28 20 10
价值:28 20 10
根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。但是果在条件中加一句当遇见单位价值相同的时候,优先装重量小的,这样的问题就可以解决.
所以需要说明的是,贪心算法可以与随机化算法一起使用,具体的例子就不再多举了。(因为这一类算法普及性不高,而且技术含量是非常高的,需要通过一些反例确定随机的对象是什么,随机程度如何,但也是不能保证完全正确,只能是极大的几率正确)。

6、如果线上用户出现502错误你怎么排查?
7、并发量很大,服务器宕机。你会怎么做?

三面

1、syn和lock的区别,哪个更好?怎么选择?
2、hashmap源码,为什么8个节点变成红黑树 又为什么到了6个节点才恢复为链表?
3、缓存穿透,怎么解决?
4、负载均衡算法,实现;
5、轮询和随机的缺点;
6、分布式服务治理;
7、dns迭代和递归的区别;
8、为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

实例3

一面

1、算法题:只包含数字和加减乘除的四则运算,例:输入 “2*3+7-4/2” 输出 11

/*---------------------------------------
*   简单四则运算
-----------------------------------------*/
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

// 简单四则运算
int calculate(string str){
    int size = str.size();
    if(size == 0){
        return 0;
    }//if
    // 数字栈
    stack<int> num;
    // 运算符栈
    stack<char> op;
    for(int i = 0;i < size;++i){
        // 数字
        if(str[i] >= '0' && str[i] <= '9'){
            num.push(str[i] - '0');
        }//if
        // 运算符 加减
        else if(str[i] == '+' || str[i] == '-'){
            op.push(str[i]);
        }//else
        // 运算符 乘除
        else{
            char o = str[i];
            int a = num.top();
            num.pop();
            int b = str[++i] - '0';
            if(o == '*'){
                num.push(a * b);
            }//if
            else if(o == '/'){
                num.push(a / b);
            }//else
        }//else
    }//for
    // 加减操作
    while(!op.empty()){
        char o = op.top();
        op.pop();
        int a = num.top();
        num.pop();
        int b = num.top();
        num.pop();
        if(o == '+'){
            num.push(a + b);
        }//if
        else if(o == '-'){
            num.push(b-a);
        }//else
    }//while
    return num.top();
}

int main(){
    string str;
    //freopen("C:\\Users\\Administrator\\Desktop\\acm.txt","r",stdin);
    while(cin>>str){
        cout<<calculate(str)<<endl;
    }//while
    return 0;
}

2、看你对docker有了解,对docker底层有了解吗?
3、看你用过的技术栈很多,你了解哪些技术栈的底层呢?
4、说一说redis的备份
5、你接下来应该还有一面

二面

1、算法题:给一个无序数组和一个target,找出数组中和target的绝对值最小的一个或者多个元素。例:输入 [1,3,2], 2 输出 [2];输入 [-1, 1, 3], 0 输出 [-1, 1]
2、看你擅长Go和Python,说说区别。
3、谈谈线程进程
4、Go的协程,并发安全,协程滥用
5、说了说项目

三面(hr面)

1、为什么choose腾讯?
2、拿到了哪些offer,对比一下优劣
3、介绍了一下部门情况。

小结

好啦。这篇文章写到这里就要划上句号了。大家看了之后,是不是感觉能够游刃有余地做出来?
这篇文章整理得可能不怎么好,如果有大佬发现了文章中存在的问题,就请在评论区中指出来(万分感谢!!!)

如果这篇文章对你有帮助,就帮我点个,点个转发,点个收藏一键三连疯狂暗示)。这对我真的很重要。谢谢各位的观看。

标签:UDP,int,儿童节,报文,面经,TCP,进程,查收,贪心
来源: https://blog.csdn.net/bug_product/article/details/117441965