小米一面面试题(自整理答案)

小米面试题

当然我还没面试过,这是牛客上面的真题。

1.HashMap
  • 1.7之前是数组+链表,1.8是数组+链表+红黑树
  • 1.7数组是Entry,采用的是头插法,在扩容时会改变链表中元素原本的顺序,以至于在并发场景下导致链表成环的问题。
  • 1.8是Node,采用尾插入,在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了。
  • hashmap扩容机制:默认是16,当超过总容量的0.75f,也就是>12时会进行扩容,为什么是0.75呢?是因为满足统计学上的柏松分布,当扩容因子为0.75时达到最高的概率。每次扩容容量变为原来的两倍。
  • 1.8后由于加入了红黑树,所以当数组某个位置的链表的节点>8时,同时数组的长度>=64时,链表转化为红黑树,如果数组长度<64,则仅仅进行数组扩容。如果链表减少到<5,红黑树就会退化为链表。
  • 如果需要并发的hashmap可以使用currentHashMap
2.线程的状态
  • 新建状态 NEW:尚未启动的线程状态
  • 就绪状态 RUNNABLE:就绪状态,排队等待CPU分配资源
  • 阻塞等待 BLOCKED :处于阻塞状态正在等待监视器锁,比如等待synchronized代码块
  • 等待状态 WAITING : 某个线程调用了Object.wait(),等待其他线程调用Object.notify()
  • 计时等待 TIMED_WAITING:比等待状态多个计时,如果超过等待时间就会进入此状态
  • 终止状态 TERMINATED: 表示线程已经执行完成
3.栈和队列的区别

共同点:

  • 都是线性结构
  • 都是只能在线性表的端点插入和删除
  • 都可以通过顺序结构和链表结构实现
  • 插入和删除的时间复杂度都是O(1),空间复杂度也是一样

不同点:

  • 队列先进先出,栈后进后出
4.事务和隔离级别

事务:

  • 原子性:事务要不全部执行,要不就都不执行
  • 一致性:当事务完成时,数据必须处于一致状态
  • 隔离性:对数据进行修改的所有并发事务彼此是隔离的
  • 持久性:事务完成后,对数据库的修改被永久保存

事务带来的四个问题:

  • 丢失修改:事务A读取一个数据,同时事务B也读取这个数据,事务A修改提交,B也修改提交,把A修改的数据覆盖了。
  • 脏读:事务A修改一个数据但还没提交,事务B读取这个数据,然后事务A运行报错,回滚了。事务B读取到的就是脏数据
  • 不可重复读:事务A读取到一个数据,事务还没结束,事务B修改了这个数据,导致事务A再次读这个数据(也就是两次读数据之间)可能不一样。
  • 幻读:事务A读取了几行数据,接着事务B插入了数据,在随后的查询中,事务A查询到原本不存在的一些数据。

隔离级别:

  • Read-Uncommitted(读未提交):允许读取到还没提交的数据,会出现脏读、不可重复读、幻读。
  • Read-Committed(读已提交):允许读取并发事务中已经提交的数据,会出现不可重复读、幻读。
  • Repeatable-Read(可重复读):Mysql的InnoDb默认的隔离级别,对同一数据的多次读取都是一样的,会出现幻读。
  • Serializable(串行化):最高隔离级别,完全符合ACID
5.乐观锁悲观锁

悲观锁

  • 每次拿数据都认为别人会去修改,所以每次拿数据的时候都会上锁,Java中的synchronized和ReentrantLock等独占锁就是悲观锁。

乐观锁

  • 每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。
6.线程和进程的区别
  • 进程是资源分配的最小单位,线程是程序执行的最小单位
  • 进程有自己的独立地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,线程没有独立的地址空间,它使用相同的地址空间共享数据。
  • CPU切换一个线程比进程花费小
  • 创建一个线程比进程开销小
  • 线程之间的通信更方便,同一个进程下,线程共享全局变量,静态变量等数据,进程之间的通信需要以通信的方式(IPC)进行
  • 多线程程序更安全,一个进程死亡不会对另外一个进程造成影响(源于有独立的地址空间),多线程程序更不易维护,一个线程死亡,整个进程就死掉了(因为共享地址空间)
  • 进程对资源保护要求大,开销大,效率相对较低,线程资源保护要求不高,开销小,效率高,可频繁切换
7.进程通信(五种)

进程间通信(IPC)

a.管道

通常是无名管道,是UNIX系统IPC最老形式
特点

  • 它是半双工,具有固定的读端和写端
  • 它只能用于具有亲缘关系的进程间的通信(也是父子进程或兄弟进程之间)
  • 它可以看成是一种特殊文件,对于它的读写也可以使用普通的read、write等函数。只存在于内存中。
b.FIFO

FIFO,也称命名管道,是一种文件类型
特点

  • FIFO可以在无关的进程之间交换数据,与无名通道不同
  • FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中
c.消息队列

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
特点

  • 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
  • 消息队列独立于发生与接收进程。进程终止时,消息队列及其内容并不会被删除。
  • 消息队列可以实现消息的随机查询,消息并不一定以先进先出的次序读取,也可以按消息的类型读取。
d.信号量

信号量(semaphore)与已经介绍过的IPC结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
特点

  • 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存
  • 信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。
  • 每次对信号量的PV操作不仅限于对信号量值加1或减1,而且可以加减任意正整数。
  • 支持信号量组。
e.共享内存

共享内存(Shared Memory) ,指两个或多个进程共享一个给定的存储区。
特点

  • 共享内存是最快的一种IPC,因为进程是直接对内存进行存取。
  • 因为多个进程可以同时操作,所以需要进程同步。
  • 信号量+共享内存通常结合在一起使用,信号量用来同步对内存的访问
8.启动线程的方式
  • 继承Thread类,implements Runnable接口
  • 实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的线程
9.gc算法,堆内存模型

gc算法有四种:复制算法,标记清除,标记整理,分代收集。

堆内存模型:私有(程序计数器、虚拟机栈、本地方法栈),公有(堆、方法区、运行时常量池)、直接内存

10.二叉树的遍历方式有几种,口述层序遍历

四种:前序、中序、后续、层序,如果使用递归遍历会比较消耗计算机资源,可以使用迭代

层序遍历一般会用队列、或者数组辅助遍历

11.快排,及其时间复杂度

排序地址

时间复杂度:O(n log n)

计算机网络

1.tcp三次握手

答案地址

2.状态码
1开头的状态码:(临时响应)表示临时响应并需要继续执行操作的状态代码。
  • 100(继续)请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
  • 101(切换协议)请求者已要求服务器切换协议,服务器已确认并准备切换
2开头的状态码:(成功)表示成功处理了请求的状态代码
  • 200(成功)服务器已成功处理了请求,通常,这表示服务器提供了请求的网页
  • 201(已创建)请求成功并且服务器创建了新的资源
3开头的状态码:(重定向)表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。
  • 300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
  • 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
4开头的状态码:(请求错误)表示请求可能出错,妨碍了服务器的处理
  • 403(禁止)服务器拒绝请求
  • 404(未找到)服务器找不到请求的网页
5开头状态码:(服务器错误)表示服务器在尝试处理请求时发生内部错误。
  • 500(服务器内部错误)服务器遇到错误,无法处理请求
  • 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
3.TCP,UDP的区别
  • TCP面向连接(传递数据前先联系),UDP是无连接的,发送数据时不需要建立连接
  • TCP提供可靠的服务,数据传输无差错,不丢失,且按序到达,UDP尽最大努力交付,即不保证可靠交付。
  • UDP有较好的实时性,工作效率比TCP高,适用于广播通信
  • TCP只能1对1,UDP可以1对1、1对多
  • TCP对系统资源要求较多,UDP对系统资源要求较少

算法题

1.合并两个数组NC22

参考力扣题

	void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int last=m+n-1;
        while(n){
            if(m==0||nums1[m-1]<nums2[n-1]){
                nums1[last--]=nums2[--n];
            }else{
                nums1[last--]=nums1[--m];
            }
        }

    }
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值