腾讯云智 后端开发-C++ 一面

1. 自我介绍

这个看个人具体情况了

2. 实习中测试业务介绍

在实习期间,我xxxx 巴拉巴拉说一堆, 如果没有也不会问这条的 看个人情况

3. 计算机网络分层介绍

常见的网络分层模型有OSI七层模型与TCP/IP模型。OSI模型自下而上依次为物理层、数据链路层、网络层、传输层、会话层、表示层与应用层;TCP/IP模型通常划分为网络接口层、网络层、传输层及应用层。分层设计降低了系统复杂性,各层独立实现特定功能,方便维护与升级。

4. TCP相较于UDP是可靠的原因

TCP是面向连接的协议,在数据传输前必须建立可靠连接。它通过序列号、确认应答(ACK)、重传机制、流量控制和拥塞控制等手段来保证数据的有序、完整传送,而UDP则没有这些机制,传输过程中可能出现数据丢失及乱序的情况。

5. TCP除了握手还保证数据可靠的机制

TCP通过以下机制确保数据可靠交付:

  • 重传机制:超时未确认的数据包会被重传。
  • 序列号与确认号:确保数据包按正确顺序到达。
  • 滑动窗口:控制未确认数据量,实现流量控制。
  • 拥塞控制:根据网络状况动态调整传输速率。
  • 校验和:检测数据在传输过程中的错误。

6. TCP三次握手机制过程

  1. 客户端发送带SYN标志的数据包,并选择初始序列号,向服务端请求建立连接。
  2. 服务端收到后回复带SYN和ACK标志的数据包,确认客户端请求并发送自己的初始序列号。
  3. 客户端收到后再发送ACK数据包,确认服务端的响应,连接建立成功。

7. 为什么三次握手中需要第三步

第三步保证客户端成功收到服务端的SYN-ACK,确保双方初始序号同步并建立一个稳定、双向确认的连接,从而防止网络延迟或丢包导致的不一致情况。

8. 计算机网络中滑动窗口及其目的

滑动窗口是一种流量控制机制,允许发送方在未收到确认数据前连续发送多个数据包,从而提高数据传输效率,同时防止接收方被过量数据淹没。其目的是在保证传输效率的同时,确保数据传输的可靠性。

9. 算法层面,滑动窗口一般怎么实现

利用环形缓冲区或队列保存未确认数据,维护窗口的起始和结束指针。收到ACK后窗口前移并释放已确认数据,若超时则重传窗口内未确认的数据,同时结合拥塞控制动态调整窗口大小,保证传输效率与可靠性。

10. 判断两个单向链表是否交叉

方法一:计算链表长度法

  1. 分别遍历两个链表计算长度。
  2. 比较两个链表的尾节点,若不同则不相交。
  3. 较长链表先走长度差步数,再同时遍历,比较节点指针是否相同,相同处即为交点。

方法二:双指针法

  1. 定义两个指针分别指向两个链表头。
  2. 当一个指针走到末尾时切换到另一个链表头继续遍历。
  3. 最终两个指针若相遇,则该处即为交点;若均为NULL,则无交点。

下面是C++代码实现示例:

#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) { }
};

// 方法一:计算链表长度法
int getLength(ListNode* head) {
    int len = 0;
    while (head) {
        ++len;
        head = head->next;
    }
    return len;
}

ListNode* findIntersection_LengthMethod(ListNode* headA, ListNode* headB) {
    int lenA = getLength(headA);
    int lenB = getLength(headB);
    
    // 让较长链表先走差值步数
    while (lenA > lenB) {
        headA = headA->next;
        --lenA;
    }
    while (lenB > lenA) {
        headB = headB->next;
        --lenB;
    }
    
    // 同时遍历寻找交点
    while (headA && headB) {
        if (headA == headB) return headA;
        headA = headA->next;
        headB = headB->next;
    }
    return nullptr;
}

// 方法二:双指针法
ListNode* findIntersection_DoublePointer(ListNode* headA, ListNode* headB) {
    if (!headA || !headB) return nullptr;
    ListNode* a = headA;
    ListNode* b = headB;
    
    while (a != b) {
        a = (a) ? a->next : headB;
        b = (b) ? b->next : headA;
    }
    return a; // 或 b
}

int main() {
    // 构造交叉链表
    // 交叉部分
    ListNode* common = new ListNode(8);
    common->next = new ListNode(10);
    
    // 链表A: 3 -> 7 -> 8 -> 10
    ListNode* headA = new ListNode(3);
    headA->next = new ListNode(7);
    headA->next->next = common;
    
    // 链表B: 99 -> 1 -> 8 -> 10
    ListNode* headB = new ListNode(99);
    headB->next = new ListNode(1);
    headB->next->next = common;
    
    ListNode* intersection1 = findIntersection_LengthMethod(headA, headB);
    ListNode* intersection2 = findIntersection_DoublePointer(headA, headB);
    
    if (intersection1)
        cout << "方法一交叉点数值为: " << intersection1->val << endl;
    else
        cout << "方法一无交叉" << endl;
    
    if (intersection2)
        cout << "方法二交叉点数值为: " << intersection2->val << endl;
    else
        cout << "方法二无交叉" << endl;
    
    // 释放内存(此处简略处理)
    delete headA->next; // 删除 7 节点
    delete headA;       // 删除 3 节点
    delete headB->next; // 删除 1 节点
    delete headB;       // 删除 99 节点
    delete common->next; // 删除 10 节点
    delete common;       // 删除 8 节点

    return 0;
}

C++面试总结 文章被收录于专栏

本专栏系统梳理C++面试高频考点,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力。

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务