华为2024嵌入式研发面试题
01 你认为最好的排序算法是什么?
在实际的编程中,最好的排序算法要根据实际需求和数据规模来选择,因为每种排序算法都有其优势和劣势。以下是一些常见排序算法及其优缺点:
- 冒泡排序 冒泡排序是一种简单直观的排序算法,它的时间复杂度是 O(n^2)。虽然它的时间复杂度比较高,但它的实现方式简单,对于小规模数据排序是非常有效的。
- 快速排序 快速排序是一种常用的排序算法,它的时间复杂度是 O(nlogn)。它的实现方式比较复杂,需要递归实现,但是对于大规模数据排序效率很高。
- 归并排序 归并排序是一种时间复杂度为 O(nlogn) 的排序算法。归并排序的实现方式比较简单,但需要额外的内存空间来存储临时数据,对于数据量较大时,空间复杂度比较高。
- 堆排序 堆排序是一种时间复杂度为 O(nlogn) 的排序算法。它的实现方式比较简单,但是需要额外的内存空间来存储堆,对于数据量较大时,空间复杂度比较高。
因此,在实际开发中,根据数据规模和具体需求来选择最优的排序算法。如果数据规模较小,可以使用冒泡排序或插入排序等简单排序算法;如果数据规模较大,可以选择快速排序或归并排序等时间复杂度较低的算法。同时,也要考虑到算法的稳定性、内存占用等因素,综合评估选择最优的算法。
02 树的遍历方式有哪些?
树是一种非线性数据结构,其遍历方式主要有三种:前序遍历、中序遍历和后序遍历。具体实现方式可以使用递归或者栈来完成。
前序遍历:先访问根节点,然后遍历左子树,最后遍历右子树。
void preorder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 访问根节点
cout << root->val << " ";
// 遍历左子树
preorder(root->left);
// 遍历右子树
preorder(root->right);
}
中序遍历:先遍历左子树,然后访问根节点,最后遍历右子树。
void inorder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 遍历左子树
inorder(root->left);
// 访问根节点
cout << root->val << " ";
// 遍历右子树
inorder(root->right);
}
后序遍历:先遍历左子树,然后遍历右子树,最后访问根节点。
void postorder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 遍历左子树
postorder(root->left);
// 遍历右子树
postorder(root->right);
// 访问根节点
cout << root->val << " ";
}
其中,TreeNode是一个二叉树节点的结构体或类,包括左子树指针、右子树指针和节点值。以上实现方式使用的是递归,也可以使用栈来完成遍历。
03 数据结构中图的概念
在数据结构中,图是由顶点和边组成的一种数据结构。它可以用来表示许多现实世界中的实体和关系,比如地图、社交网络和电路等等。在图中,顶点表示实体,边表示实体之间的关系。
图可以分为有向图和无向图。有向图中,边是有方向的,表示顶点之间的单向关系。无向图中,边没有方向,表示顶点之间的双向关系。
图还可以分为带权图和无权图。带权图中,每条边都有一个权值,可以表示实体之间的某种权重或距离等。无权图中,每条边没有权值,只表示实体之间的关系。
图的表示方式有邻接矩阵和邻接表两种。邻接矩阵是一个二维数组,其中行和列分别表示图中的顶点,数组元素表示相应顶点之间是否存在边。邻接表是由若干个链表组成的结构,其中每个链表表示一个顶点及其相邻的顶点。
图的遍历算法有深度优先搜索和广度优先搜索。深度优先搜索从起点开始,沿着一条路径一直遍历到底,然后回溯到之前的结点,继续遍历其它路径。广度优先搜索从起点开始,先遍历所有与之相邻的结点,然后再遍历与这些结点相邻的其它结点,直到遍历完所有结点为止。
04 考察链表问题
问题:输入一个链表,可能有环可能无环,有环的情况下输出入环的第一个节点值,无环的情况下输出-1。
解决方法是使用快慢指针,如果链表中有环,那么快指针总会追上慢指针,此时就可以确定链表中存在环。接下来,重新定义两个指针,一个指针从头节点开始,一个指针从环中相遇的节点开始,每次移动一个节点,直到两个指针相遇,此时的节点就是入环的第一个节点。 C++代码实现如下:
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
int findFirstNode(ListNode *head)
{
ListNode *slow = head, *fast = head;
while (fast != nullptr && fast->next != nullptr)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
slow = head;
while (slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow->val;
}
}
return -1;
}
在这个函数中,使用了两个指针slow和fast,它们从头节点开始移动。在while循环中,slow每次移动一个节点,fast每次移动两个节点。如果链表中有环,快指针最终总是能够追上慢指针,此时会进入if语句块中。在if语句块中,重新定义两个指针slow和fast,slow指向头节点,fast指向相遇节点。然后,两个指针每次都移动一个节点,直到它们相遇,此时的节点就是入环的第一个节点。如果链表中没有环,那么while循环会正常结束,返回-1即可。
05 计算机网络五层模型以及对应的协议
计算机网络五层模型以及每一层对应的协议如下:
- 物理层:负责物理传输介质上的比特流传输,例如光纤、网线等。常用协议有:RS-232、V.35、10Base-T等。
- 数据链路层:负责将比特流划分为数据帧并进行差错检测和纠正,同时也进行物理寻址和流量控制。常用协议有:以太网、令牌环、HDLC、PPP等。
- 网络层:负责数据的路由选择和分组转发,将数据包发送到目标地址。常用协议有:IP、ICMP、ARP、RIP、OSPF、BGP等。
- 传输层:提供可靠的端到端的数据传输,负责数据的分段、排序、传输错误恢复等。常用协议有:TCP、UDP等。
- 应用层:为用户提供各种网络应用服务,如电子邮件、文件传输、远程登录、Web服务等。常用协议有:HTTP、SMTP、POP3、FTP、Telnet等。
06 解释ICMP DHCP
ICMP (Internet Control Message Protocol) 是一种网络协议,它主要用于在网络中传递控制信息和错误报告。它通常被用来检测网络连接的可用性和测试网络性能,比如 ping 命令就是基于 ICMP 协议实现的。当出现网络故障时,ICMP 可以向发送端发送错误消息,以及向其他网络设备发送请求,以便进行网络故障排查。
DHCP (Dynamic Host Configuration Protocol) 是一种网络协议,它允许网络中的设备自动获得 IP 地址和其他网络配置信息。DHCP 是一种自动化的方式,使得网络管理员可以轻松地管理网络,而无需手动分配 IP 地址。DHCP 的工作原理是,当一个设备加入网络时,它会向 DHCP 服务器发送请求,请求分配一个可用的 IP 地址。DHCP 服务器会从一个可用的地址池中选择一个 IP 地址,并将该地址分配给设备。同时,DHCP 还可以为设备分配其他网络配置信息,比如默认网关、DNS 服务器等。这样,设备就可以自动获取网络配置信息,而无需手动配置。
07 HTTP 从浏览器输入域名的全过程
当浏览器输入域名并按下回车键时,HTTP(超文本传输协议)协议将开始在客户端和服务器之间进行数据传输。以下是HTTP从浏览器输入域名的全过程:
- DNS解析:当用户输入URL时,首先需要将其转换为IP地址。此过程称为DNS解析。浏览器会首先检查本地DNS缓存是否包含所请求的域名的IP地址。如果本地DNS缓存中不存在,则浏览器将向本地DNS服务器发出请求,该服务器将向互联网上的根DNS服务器发送请求,直到找到相应的IP地址。
- 建立TCP连接:一旦浏览器知道服务器的IP地址,它将通过TCP连接请求与服务器建立连接。这个过程被称为“三次握手”。在这个过程中,浏览器和服务器将交换一些数据包来确认它们的身份,以确保连接已成功建立。
- 发送HTTP请求:一旦TCP连接建立,浏览器将向服务器发送HTTP请求。该请求将包含一些信息,例如请求类型,URL,标头等。
- 服务器处理请求:一旦服务器收到HTTP请求,它将解析请求并查找所请求的资源。如果请求的资源可用,则服务器将准备响应。
- 服务器发送HTTP响应:一旦服务器准备好响应,它将使用HTTP响应将所请求的资源发送回客户端。该响应包括HTTP状态代码,响应头和响应体等信息。
- 关闭TCP连接:一旦浏览器收到响应,它将通过TCP连接关闭连接。这个过程被称为“四次挥手”。在这个过程中,浏览器和服务器将交换一些数据包以确认它们的身份,并关闭连接。
- 显示内容:最后,浏览器将使用响应的内容来显示请求的资源。这可能包括HTML,CSS,JavaScript,图像和其他资源。