双指针

双指针 快慢指针 删除有序数组中的重复项 一个有序数组nums,原地删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度 int removeDuplicates(vector<int>& nums) { int n = nums.size(); if (n <= 2) { return n; } int slow = 2; for (int fast = 2; fast < n; ++fast){ if (nums[fast] != nums[slow-2]){// fast 是读指针,不是写指针。我们无法知道前面已经写了多少个相同的值。只有 slow 才能记录我们已经保留了多少个相同的值。 nums[slow++] = nums[fast]; } } return slow; } 移除元素 在数组中,原地移除所有数值等于val的元素 ...

June 11, 2026 · 1 min · 357 words

基数与序数的规律

基数与序数的规律 ​ 对于一个数据, 要先判断是基数还是序数, 如果要计数,还要考虑是否包括边界 基数: 绝对的,有一个基底数, 日常生活中基底是1; 编程中一般是0; 常见的基数概念有 数量, 个数, 体积, 面积, 时间段, 年龄(周岁), 分数 序数: 相对的, 表示先后顺序, 常见的概念: 位次, 时间点 端点的开闭规律: 全开 ​ 基本的转换规律: 基数 = 序数 - based + 1 ...

June 11, 2026 · 1 min · 368 words

堆的核心算法解析

堆的核心算法解析 核心要点 这个精简版堆只保留了最核心的两个算法: 节点索引计算公式(堆的基础) 父节点索引 = (当前索引 - 1) / 2 左子节点索引 = 当前索引 * 2 + 1 右子节点索引 = 当前索引 * 2 + 2 核心算法1: 上浮调整 (heapifyUp) 用途: 插入新元素后维护堆性质 原理: 新元素从末尾开始,与父节点比较,如果优先级更高就向上交换 ...

June 11, 2026 · 2 min · 673 words

并发

每个线程会在进程的堆上创建的,栈之间有隔离区。 栈是默认线程独占的,而堆是共享资源,很多函数会有的缓冲区就在堆中的他是共享的。 每个线程栈和共享资源都可以看作是一个状态机。 ...

June 11, 2026 · 1 min · 346 words

并发架构与同步原语

为了追求极限性能,cpu硬件搞出了独立缓存(L1/L2)和乱序执行,但也留下了“数据不同步”和“顺序错乱”的烂摊子。硬件用MESI协议和内存屏障指令来修补。编程语言为了抹平不同平台(xv6/arm)的差异,制定了内存模型契约,让程序员通过指定内存序(relaxed/acquire/release/sc)来指挥编译器和cpu自动插入屏障。而程序员利用这些契约和底层的硬件CAS指令,最终构建出了无锁算法以及互斥锁等同步原语,为多线程并发提供了正确同步的基础设施。 ...

June 11, 2026 · 7 min · 3407 words

循环数组

循环数组 需要三个变量:头下标l,尾下标r,队列的size 范围[l, r), size== r-l 加入元素: 判断size<capacity, 将x放入尾部, 尾部++(如果超过数组边界,返回到数组开头) size++ ...

June 11, 2026 · 1 min · 162 words

调试记录:xv6 用户程序内存布局冲突异常

🛠️ 调试记录:xv6 用户程序内存布局冲突异常 1. 问题描述 (Description) 在 xv6 实验环境中,向内核添加自定义系统调用(Syscall)并编写用户态测试程序(Test Case)时,程序在系统调用逻辑执行完毕后,无法正常返回用户态继续执行。表现为进程卡死或触发硬件级页错误(Page Fault),而代码逻辑本身(内核实现)经检查无误。 ...

June 11, 2026 · 6 min · 2533 words

进程与通信

不同的进程在各自的房间内运行, 每个房间有自己的编号pid, 进程之间互不干涉, 房间内有许多种与外界通信的方式, 他们有各自的用途和特性, 分布在墙壁上; 房间内还分成多个区域, 分别是: 代码区(.text), 已初始化的全局/静态数据区(.data), 未初始化的全局/静态数据区(.bss), 堆, 栈, 内存映射区, 环境变量与命令行参数区, 内核空间 ...

June 11, 2026 · 5 min · 2039 words

链表

链表 删除特定节点 ListNode* removeElements(ListNode* head, int val) { ListNode dummy(0, head); ListNode* cur = &dummy; while (cur->next) {// if (cur->next->val == val) { ListNode* tmp = cur->next; cur->next = cur->next->next;//比条件可以多一个next delete tmp; } else cur = cur->next; } return dummy.next; } 两两交换相邻节点 ​ 在改变单链表时,优先改变上游的指针 ListNode* swapPairs(ListNode* head) { if (!head || !head->next) return head; ListNode dummy(0, head); ListNode* cur = &dummy; while (cur->next && cur->next->next) { ListNode* p1 = cur->next; ListNode* p2 = cur->next->next; cur->next = p2;//先改头->p2 cur-->p1-->p2-->other p1->next = p2->next;//在改p1->other p2->next = p1;//最后在p2->p1; cur = p1; } return dummy.next; } 合并有序链表 struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { // 创建一个哑节点作为新链表的起点 ListNode dummy(0); ListNode* curr = &dummy; // 当前指针用于构建新链表 // 同时遍历两个链表 while (l1 && l2) { if (l1->val <= l2->val) { curr->next = l1; l1 = l1->next; } else { curr->next = l2; l2 = l2->next; } curr = curr->next; // 移动当前指针 } // 将剩余部分直接连接到新链表末尾 curr->next = (l1 != nullptr) ? l1 : l2; // 返回合并后的头节点 return dummy.next; } }; 环形链表 struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; class Solution { public: bool hasCycle(ListNode *head) { // 边界情况:空链表或只有一个节点且无环 if (head == nullptr || head->next == nullptr) { return false; } // 初始化快慢指针 ListNode *slow = head; ListNode *fast = head; // 快指针及其下一个节点都非空时继续循环 while (fast != nullptr && fast->next != nullptr) { slow = slow->next; // 慢指针每次走一步 fast = fast->next->next; // 快指针每次走两步 if (slow == fast) { // 快慢指针相遇,说明存在环 return true; } } // 遍历结束未相遇,说明没有环 return false; } }; 在有序链表中删除相同元素 ​ 在链表的循环中, 判断条件一般是所有指针中最前面的指针 ...

June 11, 2026 · 2 min · 617 words

网络协议栈

现代操作系统的内核(如 Linux 内核)中有一个专门的模块叫做: 网络协议栈(Network Stack) 主要职责详解 职责 类比说明 技术术语 1. 接收和发送数据包 公司前台接收快递 & 发送包裹 数据链路层、IP 层、传输层 2. IP 地址管理 给每个员工分配邮箱地址 IPv4 / IPv6 地址配置 3. 路由选择 快递要走哪条路线最短最快 路由表(Routing Table) 4. 封装与解封装 包裹加标签 / 拆标签 数据封装(Encapsulation)与解封装(Decapsulation) 5. 传输控制(TCP) 控制文件是否完整送达 TCP 流量控制、拥塞控制 6. 端口号管理 不同部门接收不同类型的快递 端口绑定、监听、转发 7. 安全防护(防火墙) 保安检查包裹内容 Netfilter / iptables / nftables 8. NAT 转换 公司统一出口代理 Network Address Translation 9. 域名解析支持 内部电话簿查询联系方式 DNS 解析缓存、本地 hosts 10. 支持多种协议 公司支持各种沟通方式(电话、邮件、视频会议) 支持 TCP、UDP、ICMP、HTTP、HTTPS、FTP 等 类比图:操作系统网络部门的组织架构 小组 类比角色 职责 套接字接口组(Socket Layer) 客户接待员 接收进程请求(如浏览器访问网页) 传输组(TCP / UDP) 快递打包组 控制可靠传输或快速发送 网络组(IP 层) 邮政分拣中心 决定发往哪个城市(IP 地址) 链路组(MAC 层) 快递站 决定发给哪个局域网内的目标主机 路由组(Routing) 导航调度中心 选择最优路径(下一跳) 设备驱动组(NIC Driver) 快递员 实际把包裹送出去(通过网卡) 安全组(Netfilter / Firewall) 保安检查岗 检查是否允许通行 NAT 组 公司代理出口 统一管理内部员工对外通信 DNS 缓存组 内部电话簿管理员 记录域名与 IP 的对应关系 Linux 的网络部分是一个庞大的子系统,主要包括以下几个关键模块: ...

May 26, 2025 · 9 min · 4480 words