腾讯牛逼,连环追问我基础细节!

2024-01-18 14:02:24 浏览数 (1)

哈喽,大家好,我是千羽。

分享一下来自深圳大学的朋友腾讯TEG二面的面经。

上一篇面的【腾讯一面】过了,接着第二天就开始二面了,后面基本上从简单的基础算法问的比较多,还有vue,typescript等等。

然后问到项目,各个项目挨个每个都这样聊下去,每个环节问的特别的细。

  • 1.物联网工程和计算机是什么关系?
  • 2.大学学习了哪些课程?计算机系列课程学过吗?
  • 3.数组和链表有什么区别和特点
  • 4.链表有多少种类型?
  • 5.双向链表的应用场景有哪些?
  • 6.一道贪心算法题
  • 7.常见的排序算法有哪些?
  • 8.快排的实现思路是?时间复杂度是?冒泡呢?
  • 9.有用过哪些设计模式?介绍一下
  • 10.常用Vue的哪个版本?nextTick是怎么实现的?什么原理?知道process.nextTick吗?
  • 11.Vue异步更新介绍一下
  • 12.聊浏览器执行机制、事件循环、多线程架构
  • 13.Vue怎么实现数据双向绑定和视图更新
  • 14.有用过TypeScript吗?有什么好处和特点?
  • 15.聊小程序WebView预加载、热更新机制

1.物联网工程和计算机是什么关系?

我觉得物联网工程可以视为计算机科学的一个分支或扩展领域。

计算机科学在很大程度上是关注于算法设计、数据结构、操作系统、编程语言等方面,

而物联网工程则更侧重于利用计算机技术来连接和管理物理设备、传感器、执行器等,实现物与物之间的通信和数据交换。

2.大学学习了哪些课程?计算机系列课程学过吗?

有学过,计算机网络,操作系统,组成原理,数据库,前端等等

3.数组和链表有什么区别和特点

数组:

  1. 顺序存储:数组中的元素在内存中是连续存储的。
  2. 随机访问:可以通过索引直接访问数组中的任意元素。
  3. 空间固定:数组的大小在创建时就需要确定,并且不能轻易更改。
  4. 空间利用率低:对于可变大小的列表,使用数组会造成内存的浪费。

链表:

  1. 分散存储:链表中的节点在内存中可以分散存储。
  2. 可变大小:可以方便地添加或删除节点,无需像数组那样预先分配连续的内存空间。
  3. 指针链接:通过指针将各个节点连接起来,形成一条链。
  4. 查找效率低:相对于数组的随机访问,链表的访问需要从头节点开始逐个遍历节点。

4.链表有多少种类型?

主要有四种。

  1. 单向链表(Singly Linked List):单向链表是最基本的链表结构,每个节点包含一个数据域和一个指向下一个节点的指针域。单向链表的节点只能从头到尾依次访问。
  2. 双向链表(Doubly Linked List):双向链表在单向链表的基础上增加了一个指向前一个节点的指针域,使得节点可以双向遍历。双向链表的节点包含数据域、指向前一个节点的指针域和指向下一个节点的指针域。
  3. 循环链表(Circular Linked List):循环链表是一种特殊的单向链表,它的尾节点指向头节点,形成一个环形结构。循环链表的节点只能从头到尾依次访问,但可以通过尾节点回到头节点,实现循环遍历。
  4. 双向循环链表(Doubly Circular Linked List):双向循环链表是双向链表和循环链表的结合体,它的头节点和尾节点相互连接,形成一个环形结构。同时,每个节点包含数据域、指向前一个节点的指针域和指向下一个节点的指针域,支持双向遍历和循环遍历。

5.双向链表的应用场景有哪些?

据我了解到有不少场景用到。

  1. 编辑器撤销操作:编辑器通常有撤销操作,这就需要一种能够高效插入和删除数据的数据结构。双向链表由于支持O(1)时间内插入或删除某个元素,因此也是编辑器中实现撤销操作的常用数据结构。
  2. 双向循环链表:例如双向循环链表、双向块链表等。
  3. 图和树等数据结构:例如,在图的邻接表中,可以使用双向链表来表示节点之间的关系;在树的子树中,可以使用双向链表来表示节点的兄弟关系。
  4. 数据库索引:在数据库中,索引用于加快查询速度。传统的数据库索引是基于B 树的,但是如果需要频繁地插入和删除数据,B 树的修改和维护成本较高。双向链表索引的修改方便,尤其适合多次插入和删除操作的场景,因此双向链表索引在部分数据库中被使用。

6.一道贪心算法题

有1、5、10、50、100面值硬币,输入一个长度为5的数组,表示有多少枚对应面值的硬币,再输入一个需要凑齐的数值,输出最少需要多少枚

代码语言:javascript复制
public class Main {
    public static void main(String[] args) {
        int[] coins = {1, 5, 10, 50, 100};
        int amount = 113;
        System.out.println(minCoins(coins, amount));
    }

    public static int minCoins(int[] coins, int amount) {
        int[] dp = new int[amount   1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int coin : coins) {
            for (int i = coin; i <= amount; i  ) {
                dp[i] = Math.min(dp[i], dp[i - coin]   1);
            }
        }
        return dp[amount];
    }
}

在这个代码中,创建了一个长度为amount 1的数组dp,并将所有元素初始化为Integer.MAX_VALUE。

然后,我们遍历coins数组,对于每一个硬币,我们遍历从该硬币面值到目标金额的所有金额,并更新dp数组。

最后,返回dp[amount],即表示最少需要多少枚硬币。

7.常见的排序算法有哪些?

  1. 冒泡排序(Bubble Sort):通过重复地遍历待排序的序列,比较相邻的两个元素,若它们的顺序错误就交换它们,直到没有需要交换的元素为止。
  2. 选择排序(Selection Sort):在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
  3. 插入排序(Insertion Sort):将一个数据元素按其关键字的大小插入到已经排好序的有序序列中的适当位置,直到该元素插入到已排序的元素序列中成为新的已排序元素。
  4. 快速排序(Quick Sort):选择一个基准元素,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后再按此方法对这两部分记录分别进行快速排序,整个过程可以递归进行,以此达到整个数据变成有序序列。
  5. 归并排序(Merge Sort):将两个或两个以上的有序表合并成一个新的有序表。
  6. 希尔排序(Shell Sort):是插入排序的一种更高效的改进版本。通过比较相距一定间隔的元素,使得数组中较远元素之间的比较成为可能。
  7. 堆排序(Heap Sort):利用堆这种数据结构所设计的一种排序算法。
  8. 计数排序(Counting Sort):对整数进行排序的算法。
  9. 基数排序(Radix Sort):按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。
  10. 桶排序(Bucket Sort):将数据分成若干个桶,每个桶内部进行排序,然后对所有桶之间的数据进行排序。

8.快排的实现思路是?时间复杂度是?冒泡呢?

快速排序(Quick Sort)是一种分而治之的排序算法,其基本思路是选择一个基准元素,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后再按此方法对这两部分记录分别进行快速排序,整个过程可以递归进行,以此达到整个数据变成有序序列。

快速排序的时间复杂度是O(nlogn),其中n是待排序元素的个数。在最坏情况下,快速排序退化为O(n^2)的时间复杂度,但这很少发生。在实际应用中,快速排序通常具有比O(nlogn)更好的平均时间复杂度。

冒泡排序(Bubble Sort)是一种简单的排序算法,其基本思路是通过重复地遍历待排序的序列,比较相邻的两个元素,若它们的顺序错误就交换它们,直到没有需要交换的元素为止。

冒泡排序的时间复杂度是O(n^2)

9.有用过哪些设计模式?介绍一下

  1. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点来获取该实例。
  2. 工厂模式(Factory Pattern):用于创建对象的最佳实践。通过将对象的创建与使用分离,使得代码更加灵活和可维护。
  3. 建造者模式(Builder Pattern):提供了一种构建对象的最佳方式。通过将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
  4. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,所有依赖它的对象都会得到通知并被自动更新。
  5. 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。

10.常用Vue的哪个版本?nextTick是怎么实现的?什么原理?知道process.nextTick吗?

  1. Vue.js的2.x版本是最常用的。但是最近Vue2已经停止维护了。所以Vue 3.x也开始被越来越多的人使用。
  2. 关于nextTick的实现原理,有多种实现方式,其中包括使用setTimeoutsetImmediateprocess.nextTick以及MessageChannel等技术。
  3. process.nextTick()是Node.js中的一个函数,它的原理是在每个I/O型的应用中,给每一个输入输出定义一个回调函数,当I/O操作完成后,这个回调函数会被触发。然后系统会继续处理其他的请求。在这种处理模式下,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。

11.Vue异步更新介绍一下

Vue的异步更新主要通过队列和微任务来实现。当Vue检测到数据变化时,它会开启一个队列,并将所有在同一事件循环中发生的变更推入队列。这些变更包括对数据的修改、计算属性的更新等。然后,在下一个事件循环中,Vue会执行队列中的任务,并按照一定的逻辑进行DOM的更新。

在Vue中,nextTick()是一个非常重要的方法,它用于在下一个DOM更新循环结束之后执行延迟回调。通过nextTick(),我们可以确保在DOM更新完成后进行某些操作,例如获取更新后的DOM元素、执行某些依赖于DOM更新的操作等。

12.聊浏览器执行机制、事件循环、多线程架构

浏览器执行机制

浏览器的执行机制主要涉及到浏览器的渲染过程。当浏览器加载一个网页时,它会解析HTML、CSS和JavaScript代码,并生成DOM(文档对象模型)树。浏览器引擎会将DOM树与CSS结合,构建渲染树,然后对其进行布局和绘制,最终将页面呈现给用户。

其实,JavaScript的执行是单线程的,这意味着一次只能执行一个任务。所以为了防止一个长时间运行的任务阻塞其他任务,JavaScript采用了异步编程模式,如回调函数、Promise和async/await等。

事件循环

事件循环的工作原理可以简述为:当JavaScript代码执行时,如果遇到异步操作(如setTimeout、ajax请求等),这些操作会被移交给浏览器处理,同时JavaScript会继续执行后续代码。当异步操作完成时,会将对应的回调函数放入任务队列中。

当JavaScript的执行栈为空时,事件循环会从任务队列中取出一个任务并执行。这个过程会不断重复,形成一个循环,直到所有任务都执行完毕。

多线程架构

现代浏览器大多采用多线程架构,以提高性能和响应速度。

  1. 浏览器进程:负责浏览器的界面显示、用户交互以及资源管理等功能。
  2. 渲染进程:每个标签页对应一个渲染进程,负责页面的渲染和JavaScript的执行。渲染进程之间是相互隔离的,以防止一个页面的崩溃影响其他页面。
  3. GPU进程:负责处理与图形渲染相关的任务,如3D CSS效果等。
  4. 网络进程:负责处理网络请求,如下载资源、发起ajax请求等。
  5. 插件进程:负责运行浏览器插件,如Flash等。

13.Vue怎么实现数据双向绑定和视图更新

Vue.js 实现数据双向绑定和视图更新的主要机制是通过其响应式系统和虚拟DOM来实现的。

数据双向绑定

Vue 的双向数据绑定基于 ES5 提供的 Object.defineProperty() 方法来实现。该方法可以在一个对象上定义新的属性或修改现有属性,并返回这个对象。当数据对象的某个属性发生变化时,可以触发相应的操作。

  1. Observer(数据监听器):Vue 会使用 Object.defineProperty() 将所有数据的属性都转化为 getter/setter,从而实现数据的监听。当数据被读取时,getter 被调用;当数据被修改时,setter 被调用。
  2. Dep(依赖收集器):在 setter 被调用时,会通知 Dep,Dep 负责收集依赖,即收集哪些组件使用了该属性。每个属性都有一个对应的 Dep 对象。
  3. Watcher(监听器):当 Vue 实例化时,会创建对应的 Watcher 对象,用来监听每个属性的变化。Watcher 对象会读取属性的值,从而触发属性的 getter,进而被 Dep 收集。当数据发生变化时,Dep 会通知其对应的所有 Watcher 对象,Watcher 对象进而触发相应的更新函数,实现视图的更新。
  4. 指令与组件:Vue 通过 v-model 指令来实现表单元素的双向数据绑定。对于组件,Vue 提供了 props 和 $emit 来实现父子组件间的数据传递。

视图更新

Vue 的视图更新是基于其虚拟DOM来实现的。

  1. 渲染函数:Vue 组件在渲染时,会生成一个虚拟DOM树,这个过程是通过渲染函数来完成的。渲染函数是由 Vue 的模板编译器将模板编译生成的。
  2. Diff 算法:当数据发生变化时,Vue 会重新生成一个新的虚拟DOM树,然后与旧的虚拟DOM树进行比较,找出差异。这个过程是通过 Vue 的 Diff 算法来完成的。
  3. Patch:找出差异后,Vue 会生成一个 Patch 对象,用来描述如何将这些差异应用到真实的DOM上。然后将 Patch 应用到真实的DOM上,完成视图的更新。

14.有用过TypeScript吗?有什么好处和特点?

TypeScript 的好处和特点包括:

  1. 静态类型:TypeScript 提供了静态类型系统,可以提前捕捉许多常见的编程错误,提高代码的可靠性。
  2. 编译时类型检查:TypeScript 在编译阶段对代码进行类型检查,确保类型安全。
  3. 代码可维护性:由于 TypeScript 的类型系统,开发者可以更好地理解代码中的数据结构和函数参数,提高代码的可读性和可维护性。
  4. 可扩展性:由于 TypeScript 是 JavaScript 的超集,可以在现有的 JavaScript 项目中逐步引入 TypeScript,使其更容易扩展和现代化。

15.聊小程序WebView预加载、热更新机制

小程序预加载有三种方式实现:

  1. 提前请求:在用户可能导航到目标页面之前,提前发送网络请求获取页面资源。
  2. 资源缓存:将预加载的资源缓存到本地,当用户实际访问该页面时,直接从缓存中读取资源,减少网络请求时间。
  3. 预测式加载:根据用户的历史行为和习惯,预测用户下一步可能访问的页面,并提前加载相关资源。

小程序热更新机制

热更新(Hot Update)是指在不重新安装应用的情况下,动态更新应用的部分内容。

小程序热更新机制通常以下4个步骤:

  1. 检查更新:小程序在启动时或定期检查服务器是否有新版本发布。
  2. 下载更新:如果有新版本,小程序会下载更新包,通常只包含变化的部分,而不是整个应用的全部内容。
  3. 应用更新:下载完成后,小程序会在下次启动时或根据策略在后台应用更新,替换旧版本的内容。
  4. 验证和回滚:更新后,小程序会进行验证,确保新版本的稳定性和功能完整性。如果遇到问题,可以回滚到旧版本。

作者:前端LeBron

原文链接:https://juejin.cn/post/7025793782998106149

0 人点赞