环信面试

1.keras写代码

环信面试_第1张图片
2.堆和栈

堆:用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张).当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

栈:又称堆栈,用于存放程序中临时创建的局部变量

动态分配的空间来自堆空间,指针指向一个堆空间的地址,而指针本身作为局部变量存储在栈空间里

3.数组、链表、Hash的优缺点:

1、数组是将元素在内存中连续存放。链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。

2、数组必须事先定义固定的长度,不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。链表动态地进行存储分配,可以适应数据动态地增减的情况。

3、(静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小。链表从堆中分配空间, 自由度大但是申请管理比较麻烦。​数组和链表在存储数据方面到底孰优孰劣呢?根据数组和链表的特性,分两类情况讨论。

一、当进行数据查询时,数组可以直接通过下标迅速访问数组中的元素。而链表则需要从第一个元素开始一直找到需要的元素位置,显然,数组的查询效率会比链表的高。

二、当进行增加或删除元素时,在数组中增加一个元素,需要移动大量元 素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样,如果想删除一个元素,需要移动大量元素去填掉被移动的元素。而链表只需改动元素中的指针即可实现增加或删除元素。

猎户星空:python中list和dict的区别:1.list名为列表,相当于一个动态数组

2.list列表是有序的,其中的每个元素都分配一个位置索引,索引值从0开始

3.list的长度是自动变化的,list列表元素不必都是同一种类型

4.list列表可以进行截取、组合、修改、增加等操作;list列表中的元素用中括号[]来表示

Tuple

Tuple名为元组,可以看做是一种“不变”的List,即tuple一旦创建完毕,就不能修改了

Tuple元组中的元素用小括号()来表示;tuple = (3.14,'yu',[3,1,2])

print(tuple)tuple[1] = ’a',会报错

Dictionary名为字典,相当于一个HashMap

Dictionary字典查找速度快,但是代价是耗费的内存大。List相反,占用内存小,但是查找速度慢。这就好比是数组和链表的区别

Dictionary字典没有顺序,而List是有序的集合,所以不能用Dict来存储有序集合

Dictionary字典的Key不可变,Value可变。一旦一个键值对加入dict后,它对应的key就不能再变了,但是Value是可以变化的

Dictionary字典中的Key不可重复

Dictionary字典中的元素用中花括号{}来表示

2.一维数组可以用python中的dict来保存吗


完全二叉树的特点是:

1)只允许最后一层有空缺结点且空缺在右边,即叶子结点只能在层次最大的两层上出现;

2)对任一结点,如果其右子树的深度为j,则其左子树的深度必为j或j+1。 即度为1的点只有1个或0个

稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序

不是稳定的排序算法:选择排序、快速排序、希尔排序(O(1.3))、堆排序

环信面试_第2张图片
基于比较的排序算法是不能突破O(NlogN)的。简单证明如下:N个数有N!个可能的排列情况,也就是说基于比较的排序算法的判定树有N!个叶子结点,比较次数至少为log(N!)=O(NlogN)(斯特林公式)。

(1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;

(2)冒泡排序每一轮比较后,位置不对都需要换位置,选择排序每一轮比较都只需要换一次位置;

(3)冒泡排序是通过数去找位置,选择排序是给定位置去找数;

冒泡排序优缺点:优点:比较简单,空间复杂度较低,是稳定的;缺点:时间复杂度太高,效率慢;选择排序优缺点:优点:一轮比较只需要换一次位置;缺点:效率慢,不稳定


平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

指针的优缺点:

使用指针可以带来如下的好处:

(1)可以提高程序的编译效率和执行速度,使程序更加简洁。

(2)通过指针被调用函数可以向调用函数处返回除正常的返回值之外的其他数据,从而实现两者间的双向通信。

(3)利用指针可以实现动态内存分配。

(4)指针还用于表示和实现各种复杂的数据结构,从而为编写出更加高质量的程序奠定基础。

(5)利用指针可以直接操纵内存地址,从而可以完成和汇编语言类似的工作。

(6)跟容易实现函数的编写和调用。

当然,指针也是一把双刃剑,如果对指针不能正确理解和灵活有效的应用,利用指针编写的程序也更容易隐含各式各样的错误,同时程序的可读性也会大打折扣。

c语言指针占几个字节:指针即为地址,指针几个字节跟语言无关,而是跟系统的寻址能力有关,譬如以前是16为地址,指针即为2个字节,现在一般是32位系统,所以是4个字节,以后64位,则就为8个字节。

TCP/IP参考模型是首先由ARPANET所使用的网络体系结构,这一网络协议共分为四层:网络访问层、互联网层、传输层和应用层:

环信面试_第3张图片

TCP/IP协议不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族。从协议分层模型方面来讲,TCP/IP由四个层次组成:网络接口层、网络层、传输层、应用层。TCP/IP协议并不完全符合OSI的七层参考模型,OSI(Open System Interconnect)是传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这7层是:物理层、数据链路层(网络接口层)、网络层(网络层)、传输层(传输层)、会话层、表示层和应用层(应用层)。而TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。由于ARPANET的设计者注重的是网络互联,允许通信子网(网络接口层)采用已有的或是将来有的各种协议,所以这个层次中没有提供专门的协议。实际上,TCP/IP协议可以通过网络接口层连接到任何网络上,例如X.25交换网或IEEE802局域网。

Python的GC模块主要运用了引用计数来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”解决容器对象可能产生的循环引用的问题。通过分代回收以空间换取时间进一步提高垃圾回收的效率。

协程,进程,线程:协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。

一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。我们知道多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

1、进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

进程的概念主要有两点:第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。

  2、线程

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组 成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个 进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程 在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

  3、协程

  一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。我们知道多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

什么是高并发:高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPS(Query Per Second),并发用户数等。响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。吞吐量:单位时间内处理的请求数量。QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

语音助手是一款智能型的手机应用,通过智能对话与即时问答的智能交互,实现帮忙用户解决问题,其主要是帮忙用户解决生活类问题。

缺点:认为和手机对话过于尴尬、效率甚至不如自己动手操作、对话场景的识别不佳、容易出现答非所问、对带口音的人不友好

因为人工智能可以解决下面几个问题:1.首先是场景识别的过程,现在我们的语音助手都需要先来一句“Hi Siri”或者是“你好,小娜”,然后进行一问一答式的尴尬对话,这可不是我们平时和人对话的习惯。而在加入AI之后,语音助手就能够明白我们是不是在和它说话,才明白我们的命令是给它还是给别人的,整个使用过程才会变得平顺,能够随时随地进行。2.其次是语言问题,三星随着S8一起还推出了Bixby助手,但是它只支持韩文,并且有消息称三星缺乏数据和外语方面的专家,所以即使是英语版本,也还需要一段时间才会上线,语言适配显然是现在语音助手的拦路虎。并且除了官方语言之外,方言就更难对话了,毕竟绝大多数方言连标准化的发音、语法都没有,怎么将其代码化呢?3.这个时候我们就需要人工智能的学习能力了,他们会像一个人一样去学习方言中的模糊发音。而英语、普通话等官方语言的适配就更简单了,基于人工智能打造的谷歌翻译现在已经有了专业翻译的水准,人工智能的语音助手对其他语言进行翻译不是轻而易举的事情么?4.最后总结一下,随着各家公司发现“全能的”语音助手现在还比较难做到之后,他们将使用场景和功能缩小了,车载和家居环境下的语音助手还是靠谱的。但是最终目标依然还是全能语音助手,这个却需要等人工智能再发展一段时间。所以即使现在语音助手还有很多问题,但是各个科技公司还是在往这个领域疯狂砸钱,而真正的语音智能生活在他们的努力下其实也不远了

你可能感兴趣的:(环信面试)