字节商业变现

小岛面积,并将1替换成小岛面积
bfs, bfs将出队列的元素在存起来(vector<<pair<int,int>>存起来), 更新值

Ping的过程以及原理
使用的是ICMP协议(可以看作是IP层协议),(RFC规定: ICMP是任何支持IP协议的系统必须实现的)

流程:

目标IP 构建一个IP数据播啊
IP数据包加上mac地址(ARP映射表)交给数据链路层封装,组装成数据帧发送出去
主机B接收数据帧后,检查MAC地址是否为本机;如果是,解析IP数据包,根据IP协议取出 ICMP数据包;
构建一个ICMP数据包,继续往协议下层传,发送给A
A 收到数据包,根据时间差可以计算延迟

traceroute: 通过设置特殊的TTL值,根据差错豹纹找到所有路由信息(TTL=1,2,3,..)

算法题:判断一颗二叉树是不是对称

左子树反转后与右子树是否一样

算法题:输出给定数字下一个比它大的数字,比如输入:1234, 输出 1243。输入:12432,输出13224。一开始没啥想法,在面试官的指点下才勉强写出来。

找到非降序的然后找一个刚好比其大的元素替换

字节后端

mutex的底层实现
一般使用原子汇编指令实现,比如x86的tsl指令(test and set), 可以使用一条无法继续分割的汇编指令判断变量值并根据是否为0进行只为

二叉树组最大宽度
pair<> 二叉堆的id形式

1-n数字全排列
dfs

http https
首先客户端通过URL访问服务器建立SSL连接。
服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
服务器利用自己的私钥解密出会话密钥。
服务器利用会话密钥加密与客户端之间的通信。

客户端是用网站的公钥加密后的信息(会话密钥)传给网站
服务器端用自己的私钥解密

你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

线程进程的概念
一个进程可以有多个线程,至少又一个朱线程

进程之间一般来说相对独立, 有着不同的地址空间(虚存);一个进程挂,其他进程一般来书不受影响

线程往往共享这进程的资源包括存储资源,文件资源等;不同线程之间使用不同的栈进行隔离

不同线程在控制独占资源的,往往需要同步,保证不同进程访问资源的顺序,一面造成死锁

多线程:提高CPu的利用,可以将一个等待资源的线程挂起;典型的例子是计算密集型和IO密集性
另外的有点可以利用多核进行加速

启动一个线程往往鼻翼个进程快和消耗更少资源,也就是线程的力度更小;而且线程的stack一般是hot,一般不容易触发缺页终端

程序在存储空间的布局
栈, 堆, bbs区(全局变量),代码段, 常量

三数只和
target = -c 两数之和

多线程运行。讲了一下互斥量
互斥锁:
控制只有一个线程能进入临界区
控制访问资源的独占性

条件变量+互斥锁:
notify_one notify_all 满足条件的线程被重新调度
cv.wait() 满足条件,占有锁并执行后序指令;不满足条件,挂起(阻塞态)

阻塞态, 就绪态,运行态

semaphore 信号量
通过计数器控制线程的数量
P()
V()
wait()
signal()

控制线程数量可以解决哲学加就餐问题

哲学家就餐:
不同的拿叉子方式

this_threa::yield() reschedule

互斥量实现原理:
采用底层的原子汇编指令 tsl(x86) test ans set
检查并复制
如果==0就set表明占有了这个锁
反之,没有占有锁,一般的实现该线程应该阻塞

git操作。切换回某一个版本并新建一个分支:git checkout commitID, git checkout -b branchName

一个骰子,从9个人选出两个人获奖,如何公平选出两个人?
抛2次有36种可能, 所以可以的带1/9; 下一次也可从1/9 重复重抛

字节客户端

空类大小1
实际上,这是类结构体实例化的原因,空的类或结构体同样可以被实例化,如果定义对空的类或者结构体取sizeof()的值为0,那么该空的类或结构体实例化出很多实例时,在内存地址上就不能区分该类实例化出的实例,,,所以,为了实现每个实例在内存中都有一个独一无二的地址,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。可参看[深度探索c++对象模型]这本书,很不错的一本书

生产者消费者模型

一定大小的缓冲区
可以使用两个semaphore, 一个用于表示多少空缓冲区, 一个用于表示生产了多少资源

大部分系统都是低字节放在低地址,高字节放在高地址(数字类型) 小端序

网络传输 大断续

虚函数、析构函数的调用过程
虚函数 虚函数表指针(type,offset_to_top)
构造函数 虚:还没有创建
西沟函数:保证调用自己的类型的构造函数

static关键字、const关键字介绍
static: 函数,局部变量,全局变量
const: 不可修改

了解过 Linux 吗?讲讲你平时常用的一些命令?
目录文件:mkdir, touch rm cp, diff, tree, cat
磁盘: df du dd
权限: chmod
进程: htop ps -ef | grep
查找: find locate updatelocate

数组中的第K个最大元素

k 大小的最小堆

partition T(n) = T(n/2)+n

软链接 硬链接
硬连接指向与原文件统一索引节点inode index, 所以计数会自增
只有将两个文件都删掉才会从硬盘中删除文件

软连接类似与快捷,包含有另一文件的位置信息。

STL哪些情况会迭代器失效
vector<> 当前迭代器会引起后面迭代器失效

unordered_map 可能不会吧

map
multiple_map:

硬链接:新建的文件是已经存在的文件的一个别名,当原文件删除时,新建的文件仍然可以使用.
软链接:也称为符号链接,新建的文件以“路径”的形式来表示另一个文件,和Windows的快捷方式十分相似,新建的软链接可以指向不存在的文件.
下面详细介绍一下硬链接和软连接之间的区别.
1.硬链接和原来的文件没有什么区别,而且共享一个 inode 号(文件在文件系统上的唯一标识);而软链接不共享 inode,也可以说是个特殊的 inode,所以和原来的 inode 有区别。
2.若原文件删除了,则该软连接则不可以访问,而硬连接则是可以的。
3.由于符号链接的特性,导致其可以跨越磁盘分区,但硬链接不具备这个特性.

封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

非负无序整数数组[2,1,3,4,2,1],target = 3,找到target等于3的序列,使得剩下的元素最长,输出剩余元素最长的长度
要求:只能从头部找,或者尾部找或者头部+尾部找,中间不能越过元素
sum(arr)-target 的最长连续子串

malloc和new的区别

new operator expression
new experssion:

Object* o = new Object();

会先调用 new operator 申请空间,然后调用构造函数初始化,并返回指向该对象的指针

delete会先调用析构函数,然后调用delete operator释放空间

new new[] 都是operator delete delete[]

不同点:
malloc 需要size, 返回void*指针,没有申请上空间是null
new 不需要size, 返回对象类型的指针,异常(bad_alloc)

是否调用构造函数

new可以被重载,因此求存储空间可能不是堆,被称作自由存储区;但一般情况下都是堆

在stl库基础容器中挑几个讲讲功能,异同,优劣
vector deque

unordered_map/unordered_set 链表法(hash冲突的时候) 再hash, +1,1,-1,..再找空间存储

queue stack

map , multi_map(可以有相同的key) 平衡树实现的

mutex lock_guard unique_lock

lock_guardunique_lock都是对mutex的包装,是RAII的体现;保证在离开作用域的时候能够自动实现锁的释放

unique_locklock_guard更加灵活:

能够在构造的时候推迟加锁,

std::unique_lock<std::mutex> lk1(mutex1, std::defer_lock);

能够自己解锁,而不用等到析构的时候(离开作用域)才解锁;因此 condition_variable 需要 unique_lock,因为在条件不满足的时候需要解锁

两个线程不加保护地操作i++ 100次,分析过程和答案(这个我也凉了)

和写会的操作不是原子的, 所以可能写会的都是2

DNS(Domain Name System)污染是GFW的一种让一般用户由于得到虚假目标主机IP而不能与其通信的方法,是一种DNS缓存投毒攻击(DNS cache poisoning)。其工作方式是:对经过GFW的在UDP端口53上的DNS查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者返回虚假结果。由于通常的DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是无连接不可靠的协议,查询者只能接受最先到达的格式正确结果,并丢弃之后的结果。对于不了解相关知识的网民来说也就是,由于系统默认使用的ISP提供的NS查询国外的权威服务器时被劫持,其缓存受到污染,因而默认情况下查询ISP的服务器就会获得虚假IP;而用户直接查询境外NS(比如OpenDNS)又可能被GFW劫持,从而在没有防范机制的情况下仍然不能获得正确IP。然而对这种攻击有着十分简单有效的应对方法:修改Hosts文件。但是Hosts文件的条目一般不能使用通配符(例如*.blogspot.com),而GFW的DNS污染对域名匹配进行的是部分匹配不是精确匹配,因此Hosts文件也有一定的局限性,网民试图访问这类域名仍会遇到很大麻烦

TCP 可靠传输
1)校验和 Checksum(稍作了解即可)
2)序列号和确认应答机制(重要)
3)重传机制(重要)
超时重传 , 快速重传(多个ACK)
4)流量控制(滑动窗口协议)(非常重要)

累计确认
发送方的窗口和接受方的窗口
5)拥塞控制(重要)
TCP的报文有窗口字段,一般来由接受方窗口大小确定
拥塞窗口cwnd 由发送方维护的状态变量,根据网络的拥塞程度动态变化
发送窗口是cwnd和接受矿口的最小值
慢开始,拥塞避免,快重传, 快恢复