gzh上面的mst

文章目录

  • 数字圆环
    • 思路
  • 有条件的排序数组
    • 思路
  • 腾讯wxg的后台开发
    • struct和class的区别?

数字圆环

  • n个数, ≥ 1 \ge 1 1的正整数
  • 是否满足该数比相邻两数相加之和小,从而形成一个数字圆环,
  • an的相邻两数为 a n − 1 a_{n-1} an1 a 1 a_1 a1
  • 顺序可调换
  • 输入为1 7 3 5
  • 可得出1 3 7 5 满足数字圆环

思路

  • 先sorted这数组
    • 每个元素右边一定有个元素是$\ge $他
    • 再加上左边的元素就肯定满足
    • 该数比相邻两数相加之和小
  • 最后一个数咋办?
  • 只需判断最后一个元素和
    • 倒数第二第三和是什么关系
    • < < <则调整倒数第一个和倒数第二个
    • > > >不能就无法满足
      • 其他元素都满足该数比相邻两数相加之和小

有条件的排序数组

  • n个数,对这个数组任意次以下操作:

  • 如果 a i + a j a_i+a_j ai+aj为奇,那么就可交换这两个数

    • 允许交换次数不限
  • 求出能通过若干次操作后得到的数组中

    • 字典序最小的一个
  • 输入 7 3 5 1 输出 7 3 5 1

  • 输入

  • 53941 38641 31525 75864 29026 12199 83522 58200 64784 80987

  • 输出

  • 12199 29026 31525 38641 53941 58200 64784 75864 80987 83522

思路

  • 要两数相加为奇数,
  • 以下三种情况
  • 全奇 (两两都交换不了)
  • 全偶 (两两都交换不了)
  • 有奇有偶 (两两有些能直接交换,有些能间接交换)
  • 有些能间接交换。
    • 输入5 6 4 3 1
    • 要让1排在最前面,1和5之间可以直接交换吗?
    • 不可以,但1和5之间可以通过一个偶数(4)来间接交换。
    • 当数组既有偶又有奇就可以任意交换
#include 
#include 
#include 
#include 
#include 
 
const int N = 1e5 + 10;
 
int a[N];
 
using namespace std;
int main()
{
    int n;
    cin >> n;
    int odd = 0,even = 0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        if(a[i]%2==0)
            even++;
        else
            odd++;
    }
    if(even>0 && odd>0)
        sort(a,a+n);
    for(int i=0;i<n;i++)
    {
        printf("%d%c", a[i], i == n - 1 ? '\n' : ' ');
    }
    return 0;
}

腾讯wxg的后台开发

  • 对OS底层知识要求很高,
  • 准备把《鸟哥的Linux私房菜》这本书刷一遍。

  • 给定表达式,1*2+3/5+7,操作符只有加减乘除,没括号,

  • 数字是非负。

  • 编写一个程序输出表达式的结果。

  • 符号栈和数字栈

  • 读新符号

    • 看符号栈有没有>=该符号的运算符,
    • 有的话就把符号栈里面的一个一个干掉
    • 然后把这个符号进栈
gzh上面的mst_第1张图片
  • 最后把符号栈里剩余的符号依照出栈的顺序进行运算即可。

  • python的eval可直接解析表达式并得出结果:
    exp=input()
    print(eval(exp))

  • 设人群有1%罹患某种疾病,99%健康
  • 某种检验手段,误检的概率是1%,就是说,健康的人有1%被误检为阳性,患病的人有1%被误检为阴性。
  • 当某个人体检时被检出阳性,那么他已经得病的概率是多大?
gzh上面的mst_第2张图片

  • 广州对外地车牌实行开四停四,

  • 实现一个算法,根据以往若干天的行驶情况,判断它在哪几天违章。

  • 开四停四是指你最长的连续开车间隔不能超过4天,

    • 如果你连续开了4天车必须休息4天再继续开。
    • 这个连续开车间隔是允许中间有一些天是没有开的。
    • 也就是说你开车的时间里最近的连续开车起点不能超过4天。
    • 那么如何判断开车起点再哪呢?
    • 我们可以看看开车的那一天的前面是不是已经有4天没开车了,
    • 如果是的话说明这个点可以作为起点。

题目本身很简单,但理解这个规则还是需要逻辑清晰点的。

struct和class的区别?

  • C++里,struct和class都是类,
  • 如不特殊声明,
    • struct成员均为public,class的成员均为private
    • struct默认是public继承,class默认是private的继承
  • C++之所以有struct这个关键字主要是向C兼容
  • C里struct只能定义成员变量却不能定义成员函数。

__func__和__LINE__的实现机制是怎么样的?
__func__是C++11里的一个预定义变量,__LINE__是一个宏,__LINE__在预处理阶段展开,而__func__在编译期做完词法分析后获得AST后可以很轻易的展开(应该是在语义分析阶段)

  • 虚函数的实现原理?
  • 虚函数的实现和虚函数表(虚表)和虚函数表指针(虚指针)有关。
  • 每个定义了虚函数的类都会有个自己的虚表,负责存放对应虚函数的函数指针。而每个对象都有一个虚指针,指向对象所属类的虚表(如果是多继承的话会有多个虚指针,通过不同的名字区分)。这个虚指针在构造函数执行的时候被初始化:首先默认执行父类的构造函数,此时虚指针存放的是父类的虚表地址,再执行子类的构造函数,这样虚指针就被替换成子类的虚表地址。(进一步展开,这也是为什么构造函数不能是虚函数的原因,因为在执行构造函数前,虚指针还没有被初始化!)

解释一下TCP的流量控制和拥塞控制有什么不同?具体机制是怎么样的?
这个非常基础了,流量控制是用来防止接收方缓存不够的情况的,由接收窗口rwnd控制,如果发送方检测到rwnd=0,那么就会发送一个空数据包并停止继续发送数据而拥塞控制是用来防止由于网络拥堵导致丢包的情况,由拥塞窗口cwnd控制,拥塞控制有三个模式:慢启动,拥塞避免和快速恢复。(剩下还回答了好多细节,这里就不贴了)
简述一下TCP的三次握手机制?
emmm这个太简单了,不讲

  • http和https吗?
    https指的是http+TLS/SSL,即在http之上加入了安全套接层(但从协议栈上看,TLS/SSL的上级协议是http协议)。由于http的所有内容在网络上以明文传输,可以被所有中间节点看到,所以有巨大的安全风险(特别是传输一些敏感信息的时候)。https则会把内容加密后再进行传输,中间节点无法得知真实内容,可以避免此类的安全问题。

https的加密机制了解吗?
https的加密既使用了对称加密也使用了非对称加密。首先,服务器生成非对称加密算法所需的公钥和私钥,将公钥明文传给客户机,客户机在本机上生成对称加密所使用的通讯密钥,用公钥加密发送给服务器,由于公钥加密后的密文只能通过私钥解开,因此传输节点无法得知通讯密钥内容。这样后续交流双方只需要使用通讯密钥加密信息就可以实现安全通信了。

但是如果传输过程中存在一个中间人,他把服务器的公钥换成自己的公钥传递给客户机,这样客户机发送通讯密钥的时候中间人就能通过自己的密钥解开,得到通讯密钥,再用服务器的公钥加密后传回给服务器。此时,中间人就在客户机和服务器没有察觉的情况下成功窃听到了信息。为了防止这样的情况发生,我们需要验证公钥是否真的来自于服务器。

这时候我们想到可以找一个受信的第三方(也就是CA),把公钥,域名,第三方机构等信息放在一起做一次hash(做hash的目的是把这些信息变成定长的比特串,降低非对称加密所需的时间,因为如果内容很长的话加密时间也会很长),再用CA的私钥加密,得到一个对内容的签名,由于中间人无法得到CA的信任,因此即使中间人可以伪造证书,也无法伪造签名。

现在,服务器直接发送证书和证书签名,当客户机收到证书和签名时,他首先找到是哪个CA发行了证书,再用CA的公钥解密签名,与客户机自己对证书生成的hash对比,如果一致就说明这个公钥是可行的,可以确定是服务器传过来的公钥了!(证书)
https的握手机制?
客户机发出hello连接请求,附上自己支持的安全协议的版本,能够使用的加密套件的列表等相关信息。
服务器回应hello请求,根据本机上能使用的加密套件,发送此次握手使用的协议版本,哪种加密套件以及自己的证书。
客户机收到信息后,验证证书真伪,如果通过验证就在本地生成通讯密钥,通过公钥加密发送给服务器
服务器收到信息后,通过私钥解密获得通讯密钥
后续通讯均通过通讯密钥加密进行

  • 如果C++中assert发现出错,linux会如何处理?
  • 如果assert的时候发现表达式为false,assert会打印错误信息,然后调用abort结束程序,不进行清理,后续的操作留给操作系统处理。
  • 此时linux会强制kill掉该程序,留下一个僵尸进程等待父进程或init来处理。僵尸进程我当时没答出来,后面问了同学才知道。

  • 进程和线程的区别?
  • 进程是资源分配的最小单位,线程是CPU调度的最小单位
  • 每个进程有自己的PCB,有单独的代码和地址空间。
  • 而一个进程下的线程共享代码和地址空间。
  • 线程相比于进程,线程间切换的消耗更小。
  • 相比于进程,线程如果崩溃对系统造成的

  • linux下进程间通信的几种方式?
  • 管道,命名管道,消息队列,共享内存,信号量,套接字,信号。

了解epoll吗?

linux下有五种OS模型,分别是:阻塞型,非阻塞型,IO多路复用型,信号驱动型,异步IO型。大部分socket接口都是阻塞型的,但有一个巨大的缺点就是如果要读取的socket未就绪进程就会阻塞,这导致一个进程同时处理一个socket,如果同时有多个访问就要对每个访问单独开一个进程处理,这会占用大量的系统资源。而使用IO多路复用则是由一个进程同时监视多个socket,当这些socket中的一个准备就绪后进程对此进行处理,这样就节省了内存资源。IO多路复用比较适合于处理连接数较多,但活跃连接数较少的情况,比如提供web服务。在linux下常用的多路复用函数有select,poll和epoll。select和poll查询socket是否就绪使用的是轮询法,效率是,而epoll由内核直接支持,通过callback直接将对应的文件标识符加入就绪队列,从而达到的时间复杂度。epoll实际上是一组函数,包括epoll_create,epoll_ctl和epoll_wait。

在触发方式上,epoll有ET(边缘触发)和LT(水平触发)两种模式,在ET模式下,仅当socket刚刚就绪时会触发epoll,epoll告诉我们该socket就绪。如果没有及时处理,epoll不会再次告知我们。

  • 二面

C++

  • 指针和数组名有区别?
  • 数组名被解释为其第一个元素的地址,
    • 对数组名应用地址运算符(即&)时,得到的是整个数组的地址。
  • 使用sizeof对数组名运算时,得到的是整个数组的长度,
    • 对指针sizeof得到指针长度
  • 数组名作为参数传入函数时,
    • 数组名会退化成指针
void func(int arr[]){
 cout<<sizeof(arr)<<endl;//输出4
}

  • C++的内存布局是怎么样的,从低到高分别是哪些区域?
  • 从低到高代码区,全局变量区,堆,栈,文字常量区。
    • 堆的分配由低地址到高地址,栈的分配由高地址到低地址。

linux下有哪些进程间通信的方法?哪一种最快?

这个问题一面也问到了,这里不再重复。进程间通信最快的方法是共享内存法,因为并不需要拷贝,直接通过某些手段把同一段内存映射到两个进程的地址空间中。

linux中进程的内存布局是怎么样的?
又是内存布局……我依然不会,只能随便扯了一点和虚拟内存相关的东西。这里附上一个知乎答案里的图来解释:

假设在linux下,有一个程序首先读入一个文件,修改了其中的内容,再写入原文件中,请你谈谈在这个过程中OS做了哪些工作。
这个问题一下就问到很底层的知识了,只能很浅显的说了一些我会的,如果大家会这道题可以帮我补充一下。。
数据库

了解mySQL中的存储引擎吗?
这个以前上实验课的时候了解过,但是好久没看不记得了……mySQL的两个最主流的储存引擎是MyISAM 和 InnoDB,通常我们使用的是InnoDB。他们的差别:
InnoDB支持事务,MyISAM不支持。
InnoDB支持外键,MyISAM不支持。
InnoDB是聚集索引,MyISAM是非聚集索引。
InnoDB不保存表的具体行数,MyISAM保存了表的具体行数
InnoDB最小的锁粒度是行锁,MyISAM是表锁。
通常来说,InnoDB适合增删改多,且需要事务支持的情况,而myismp支持高效率查找,适合读比较多的情况。
事实上,mySQL的储存引擎还有MEMORY,ARCHIVE等,他们各有各自的优缺点。但主流的还是上面提到的两个储存引擎。

如何优化SQL的查询速度?
这个不知道怎么回答……我说了可以建立索引,分页,缓存部分内容到内存(比如redis就是类似的原理)三个方法,也不知道对不对。

  • 100万*100万图,
    • 里面有一条像素点构成的首尾相接的曲线,
    • 这个曲线形成了一个闭合区域,
  • 现给定你这些像素点坐标,如何判断一个某个点在里还是外。

这个问题可以转化成求一个点是否在一个多边形内部。我们首先可以进行一个简单测试,先取得这些像素点的最大和最小x,y坐标,构成一个恰好将闭合区域包裹在里面的四边形,看看这个点是否在该四边形里面,如果不在那么肯定不在多边形内部。接下来我们采用射线法:过给定点做一条与x轴平行的射线,这条射线会和多边形形成一系列交点,如果交点数量是奇数,那么就说明在多边形内部,否则就在外部。当然这样是没有考虑一些特殊情况的,更加详细的解答可以参考这个链接。

  • 一颗二叉树,每个节点有一个唯一的值id,
  • 现在给定三个不同的id值a,b,c,
  • 问他们所属的节点的LCA是哪个节点?

这个问题很简单,用tarjan跑一遍就出来了。不懂的同学可以学一下求LCA的tarjan算法。

你可能感兴趣的:(interview)