IP 地址 IP address
是什么:每台联网设备的“门牌号”,一串数字,比如 1.2.3.4。只有拿到对方的 IP,别人才找得到它。
什么时候用:登录服务器、配域名解析、排查网络时都会用到。注意区分「公网 IP」(外面能访问)和「内网 IP」(只在局域网内有效)。
- 云服务器:控制台「实例」页看公网 IP。
- 登录:
ssh root@你的公网IP - 解析:在 DNS 的 A 记录里填这个 IP。
- ⚠️ 公网 IP 等于服务器的门牌号,别写进公开博客。
配合博客学习路径使用,遇到陌生概念来这里查。每条词条按「是什么 → 什么时候用 → 怎么用 → 相关词条」组织;从文章跳进来,看完点「返回刚才的文章」就能回去。
是什么:每台联网设备的“门牌号”,一串数字,比如 1.2.3.4。只有拿到对方的 IP,别人才找得到它。
什么时候用:登录服务器、配域名解析、排查网络时都会用到。注意区分「公网 IP」(外面能访问)和「内网 IP」(只在局域网内有效)。
ssh root@你的公网IP是什么:一台长期开机、有公网 IP 的电脑,负责收请求、跑程序、回内容。网站、机器人、API、网盘都住在上面。
什么时候用:需要后端(登录、数据库、定时任务)、需要 24 小时在线、或者想把 AI 模型部署给别人用时。
ssh root@公网IPapt update && apt install nginx php mysql是什么:浏览器能访问的内容,本质是「文件」(HTML/CSS/JS),需要互动时再加后端程序和数据库。
什么时候用:博客、作品集、工具站用静态页就够;需要登录/评论/动态内容再上后端。
index.html,推 GitHub Pages / Vercel,免费。是什么:IP 的好记名字,如 example.com。结构上由「名字 + 后缀」组成,后缀叫顶级域(.com / .icu / .cn),前面还可以加 www、blog 等子域名。
什么时候用:让别人不用记一串数字;做邮箱、短链接、个人品牌时也需要。
ping 你的域名 确认解析成功。是什么:定位某个资源的完整地址,格式为「协议 + 域名 + 路径」,如 https://example.com/posts/a.html。
什么时候用:填站点地址、发链接、配重定向时。
http(明文)→ 尽量用 https(加密)。https://域名。是什么:把「域名」翻译成「IP」的分布式通讯录。你在域名服务商那里写的「解析记录」,决定访问域名时去哪个服务器。
什么时候用:把域名指向服务器、配邮箱、做子域名时。
@(或 www),记录值填公网 IP。ping 域名 或 nslookup 域名。是什么:同一条域名可以配置多种“指令”,不同类型管不同的事。
什么时候用:建站用 A,别名用 CNAME,邮箱用 MX,验证归属用 TXT。
www → 主域名。是什么:一台服务器有多个“门”,每个服务占一个门。比如网页走 80/443,SSH 走 22,数据库默认 3306。
什么时候用:配置防火墙、Nginx 监听、访问数据库/API 时都要写对端口。
是什么:远程安全登录服务器的协议,默认端口 22。有两种登录方式:密码 和 密钥(更安全、免密)。
什么时候用:管理服务器、往服务器传代码、GitHub 免密推送。
ssh root@公网IP,回车输密码。ssh-keygen -t ed25519(一路回车)。ssh-copy-id root@公网IP;加 GitHub:Settings → SSH keys。ssh -T git@github.com是什么:控制“外面能不能访问某个端口”的门卫。云厂商的叫「安全组」,服务器系统里还可以用 ufw/iptables。
什么时候用:新服务器第一件事就是放行 22;建站再加 80/443。
0.0.0.0/0。ufw allow 22/tcp、ufw allow 80/tcp、ufw enable。是什么:中国大陆机房里的网站,上线前要在工信部登记网站主体(个人或企业)和内容。规则是「谁接入谁备案」——服务器在哪家云,就在哪家备案。
什么时候用:服务器在大陆、要用域名提供网站服务时。香港/海外服务器不需要。
beian.miit.gov.cn。是什么:把网站通信加密的“锁”。装了证书,地址变 https://,别人窃听不到内容,浏览器也不会提示“不安全”。
什么时候用:任何正式上线的网站都要用;有登录、支付、表单时尤其重要。
apt install certbot python3-certbot-nginxcertbot --nginx -d 你的域名 -d www.你的域名--redirect 或手动加 301。是什么:最常用的 Web 服务器:接收浏览器请求,把静态文件直接返回,把 PHP/后端请求转给对应程序(这就是“反向代理”)。
什么时候用:几乎所有 Linux 建站都会用到;还能做 HTTPS、负载均衡、缓存。
apt install nginxserver_name 域名、root 网站目录、PHP 转发到 php-fpm.sock。nginx -t;生效:systemctl reload nginx/etc/nginx/sites-available + 软链到 sites-enabled。是什么:最流行的开源建站程序(PHP 写的),自带可视化后台,发文、换主题、装插件都在网页里点。
什么时候用:不想手写页面、想要后台管理文章和评论时,博客/作品集/企业站都能用。
/var/www/blog),目录属主设为 www-data。/wp-admin 写文章、改主题;及时更新版本和插件。是什么:一种后端语言,WordPress 就是用它写的。Nginx 本身不处理 PHP,需要交给 php-fpm 处理。
什么时候用:跑 WordPress / Typecho 等 PHP 程序时。
apt install php8.1-fpm php8.1-mysql(按需加 gd/curl/xml 等扩展)。.php 请求转发给 php8.1-fpm.sock。systemctl reload nginx是什么:程序持久化存数据的仓库。博客用 MySQL/MariaDB 存文章、用户、评论;大数据/灵活结构也会用 MongoDB。
什么时候用:WordPress 安装时、任何需要登录/存储的程序里。
sudo mysqlCREATE DATABASE blog ...; CREATE USER ...; GRANT ...; FLUSH PRIVILEGES;localhost。mysqldump blog > blog.sql;恢复:mysql blog < blog.sql是什么:不买服务器也能放网站的云服务,如 GitHub Pages、Vercel、Netlify。适合静态站(无后端)。
什么时候用:作品集、文档站、纯展示页;想快速上线、省维护时。
是什么:用海量文本训练出来的“文字大脑”,能理解问题并生成回答。常见的有 GPT、Claude、DeepSeek 等,以及 Llama、Qwen 等开源模型。
什么时候用:写文案、答疑、写代码、做助手。要“自己动”就升级成 Agent(加工具)。
messages(system/user),取回 content。是什么:模型处理文本的最小单位。中文大致 1 个字 ≈ 1~2 Token;它决定两件事:计费和能记住的长度。
什么时候用:估算成本、判断“怎么又超出上下文了”时。
是什么:API 是“接口”,让程序按固定格式请求模型;API Key 是证明“你是谁”的钥匙,直接关系账户里的钱。
什么时候用:程序要调云端模型、或自己部署模型给别人调用时。
export OPENAI_API_KEY="sk-..."(Windows:$env:OPENAI_API_KEY="...")。from openai import OpenAI; client.chat.completions.create(...)是什么:你发给模型的指令。同样的模型,指令写得好不好,结果天差地别。研究怎么把指令写好就叫 Prompt 工程。
什么时候用:每次调用都在写 Prompt;复杂任务尤其需要结构化。
是什么:模型一次能“同时看到”的内容上限(按 Token 算)。超过部分它根本看不到。
什么时候用:长文档、长对话、多轮 Agent 循环时最容易“爆上下文”。
是什么:让模型“带资料答题”:先把你的文档变成可检索的库,提问时先查出相关片段,再连问题一起交给模型。
什么时候用:想让 AI 回答你私有的 PDF/笔记/文档,而不是瞎编时。
是什么:把文字变成一串数字(向量)。语义越接近的文字,向量距离越近——这是“机器能算相似度”的基础。
什么时候用:做相似搜索、RAG 资料库、去重、推荐时。
是什么:能自己“规划 → 调工具 → 看结果 → 继续做”直到完成任务的小程序,而不是一问一答的聊天框。
什么时候用:任务需要多步、需要查数据/执行代码/操作文件时。
是什么:模型不自己执行操作,而是输出“我要调用函数 X,参数是 Y”,由你的程序真正执行——这是 Agent 的“手”。
什么时候用:让模型查天气、算数、读文件、发请求时。
tool_calls。role:"tool" 消息返回。是什么:用你自己的数据继续训练模型,让它更懂你的语气、格式或业务规则。比 Prompt 重,属于“深度定制”。
什么时候用:Prompt/RAG 都试过仍不够,且你有成对的数据(问题+标准回答)时。
是什么:把模型的数字精度降低(如 16 位 → 4/8 位),体积和显存占用大幅变小,质量略降。这是本地跑大模型的“魔法”。
什么时候用:显存/内存不够、想在个人电脑或小服务器上跑模型时。
Q4_K_M/Q5 家用推荐,Q8 更准但更大。ollama run 模型名是什么:模型“生成回答”的运行过程,主要吃显卡显存(VRAM)。部署模型本质上就是“起一个推理服务”。
什么时候用:本地部署选工具、估算能不能跑、排查“怎么这么慢”时。
nvidia-smi),决定能跑多大模型。是什么:一条命令在本地跑开源模型的小工具,会自动下载并管理量化模型,还自带一个 OpenAI 兼容接口,最适合入门本地部署。
什么时候用:想在个人电脑上免费跑模型、研究本地部署、不想把数据发到云端时。
ollama run llama3(或 qwen3 等)。ollama list;删除:ollama rm 模型base_url="http://localhost:11434/v1",api_key 随意。是什么:面向高并发的推理引擎,显存利用率和吞吐比裸跑高很多,适合放在服务器上服务多个用户。
什么时候用:有 GPU 服务器、多人同时调用、追求吞吐和稳定时。
pip install vllmvllm serve Qwen/Qwen2.5-7B-Instructhttp://0.0.0.0:8000/v1,OpenAI 格式直接调。--max-num-seqs 等参数。是什么:一套被广泛使用的调用格式。云厂商、Ollama、vLLM 都提供兼容接口,所以换模型常常只改一行 base_url。
什么时候用:在云 API 和本地模型之间切换、或想“代码写一次到处跑”时。
base_url:云端填官方地址,本地填 http://localhost:11434/v1。model:写服务端支持的模型名。api_key:云端填真 Key;本地一般随便填。是什么:源代码变成可执行文件的两个阶段:编译把每个 .cpp 单独翻译成目标文件,链接把所有目标文件和库拼成可执行文件。
什么时候用:报错时先分清是编译错误还是链接错误——两类错误的排查方向完全不同。
g++ -std=c++17 -o app main.cpp 一条命令里其实自动做了编译 + 链接。undefined reference 就是链接错误:函数声明了但没实现,或源文件没参与编译。是什么:给编译器的开关,最常用的是 C++ 标准版本和警告等级。
什么时候用:每天都在用;写代码时把警告全开,能提前发现一半的低级错误。
-std=c++17 指定标准版本;课本里用到结构化绑定、if 初始化就必须 C++17。-Wall -Wextra 打开大部分警告;-Wpedantic 拒绝非标准写法。-g 保留调试信息,-O0 关优化,配合调试器使用。-fsanitize=address,undefined 打开内存与未定义行为检测(见 Sanitizer)。是什么:存放声明(函数原型、类定义、模板)的文件,用 #include 在编译前原样展开。
什么时候用:多文件工程里区分“对外暴露的声明”和“内部实现”时。
#pragma once(或 include guard)防止重复包含。#include <vector> 用尖括号找系统目录;#include "util.h" 用引号先找当前目录。是什么:给名字划分地盘,避免不同库里的同名函数/类撞车。
什么时候用:自己写库、或把代码拆成多个模块时。
namespace math { int add(int, int); } 定义,math::add(1, 2) 调用。using namespace std;——会把污染带给所有引用者。是什么:同一个实体在整个程序里只能有一份定义;inline 函数、模板、类定义属于例外(可以多份但必须完全一致)。
什么时候用:遇到“重复定义 / 符号重定义”链接错误时。
inline(模板和类内成员函数天然满足)。extern 声明。是什么:C++ 的输入输出机制:std::cin 读、std::cout 写,用 << 和 >> 连接数据。
什么时候用:所有需要读入数据、输出结果的程序。
std::cout << a << '\n'; 不会自动加空格或换行,分隔符要自己写。std::cin >> x 跳过空白;读整行用 std::getline,两者混用前先 std::cin.ignore()。std::ios::sync_with_stdio(false); std::cin.tie(nullptr); 提速。是什么:变量在诞生时有没有被赋值。C++ 不初始化就是“里面是垃圾值”,读它是未定义行为。
什么时候用:每次声明变量时——默认用花括号 {} 最省心。
int a; 未初始化,读它是 UB;int a{}; 一定是 0。int n{3.14}; 会编译报错(禁止窄化),int n = 3.14; 会静默丢小数。std::vector<int> v(5) 是 5 个 0,v{5} 是 1 个 5。是什么:数值超出类型能表示的范围。C++ 里有符号整数溢出是未定义行为(不是“回绕”),无符号才回绕。
什么时候用:做累加、乘法、下标计算时,只要可能超过 21 亿就要警觉。
long long(64 位,约 9×10^18)。long long s = a + b; 再和 int 边界比。1 << 31 是 UB,写 1LL << 31。是什么:把一种类型转成另一种。C++ 提供四种具名转换,比 C 风格 (int)x 更明确。
什么时候用:整数除法想得到小数、指针类型互转、去掉 const 等场景。
static_cast<double>(a) / b:最常见,编译期检查。dynamic_cast 用于多态向下转换(运行期检查);const_cast 只改 const;reinterpret_cast 最危险。5 / 2 得 2。是什么:变量的别名,必须在定义时绑定,之后不能改绑;不存在空引用。
什么时候用:函数参数想“零拷贝又只读”用 const T&;要写回调用方的变量用 T&。
const std::vector<int>& v 是最高频的参数写法:不拷贝、不会改。是什么:存放内存地址的变量,解引用(*p)就能读写那块内存。
什么时候用:需要表示“可能没有”、需要指针运算、需要和 C 接口打交道时。
int* p = &a; 取地址,*p = 5; 改写;p->member 访问成员。nullptr,不要用 NULL 或 0。是什么:用 const 表达“这里不该改”。它既是给编译器的约束,也是给调用方的承诺。
什么时候用:参数、成员函数、指针/引用组合时都要想一遍。
const int* p(不能改值)、int* const p(不能改指向)、const int* const p(都不能)、int* p(都能)。int size() const)表示不修改对象,const 对象只能调用这类函数。const T& 立刻理解为“只读且不拷贝”。是什么:栈上对象随作用域自动创建和销毁;堆上对象要手动 new/delete(或用智能指针接管)。
什么时候用:决定“这个对象该放栈还是堆”是 C++ 的基本判断。
Point p{1, 2}; 离开作用域自动析构,零额外开销。auto p = std::make_unique<Shape>();是什么:对象从构造完成到析构开始之间的时间;离开作用域、delete、容器清空都会结束生存期。
什么时候用:排查“用了已经销毁的对象”(悬垂引用/指针)时。
delete 或智能指针释放时销毁。是什么:把资源的申请放在构造函数、释放放在析构函数:对象活着资源就在,对象销毁资源就还。
什么时候用:管理内存、文件、锁、socket 等任何“用完要还”的东西。
std::vector/std::string 代替裸数组/char*。std::unique_ptr 接管 new 出来的对象。是什么:用对象封装裸指针,离开作用域自动 delete:unique_ptr 独占、shared_ptr 共享计数、weak_ptr 不增加计数。
什么时候用:需要堆对象时的默认选择;只有“观察”用途才用裸指针。
auto p = std::make_unique<T>(args); 创建,独占所有权,不能拷贝。auto p = std::make_shared<T>(); 共享,use_count() 查看引用计数。std::move(p) 转移 unique_ptr 的所有权;用完记得置空或离开作用域。是什么:类是“数据 + 操作数据的方法”打包成的类型;对象是它的实例。C++ 里 struct 和 class 只差默认访问权限。
什么时候用:把一组相关的数据和函数组织在一起时。
.,指针用 ->。double x = 0.0;。double dist() const;是什么:构造函数把对象初始化到位;析构函数在对象销毁时收尾(释放资源)。
什么时候用:类里需要初始化成员、申请/释放资源时。
Buffer(std::size_t n) : data_(n, 0), size_(n) {}()。explicit,防止隐式转换。virtual,否则 delete 基类指针不会调用派生类析构。是什么:编译器会自动生成拷贝构造、拷贝赋值、析构等;一旦类里自己管理了裸资源,就得自己写全套。
什么时候用:类里有裸指针/裸数组时;其它情况优先用零法则。
*this。是什么:让自定义类型支持 +、<、[]、<< 等运算符。
什么时候用:希望自己的类型能直接排序、能像容器一样用下标、能直接打印时。
bool operator<(const T& o) const 之后就能直接 std::sort 和放进 set/map。<= 会让 sort 行为未定义。= [] () -> 必须是成员函数;<< 输出运算符写成自由函数(左操作数是 ostream)。是什么:派生类继承基类接口;只有虚函数才是运行期动态绑定(按实际对象类型调用)。
什么时候用:需要通过基类指针/引用统一处理多种派生类型时。
virtual double area() const = 0;(纯虚),派生类写 override 让编译器检查签名。是什么:把类型当参数:一份代码,编译器按调用处的类型生成多份具体实现。
什么时候用:需要写“对所有类型都成立”的函数或容器时(顺序表、栈、最大值……)。
template <typename T> T maxOf(T a, T b); 调用 maxOf(3, 5) 自动生成 int 版本。是什么:C++ 标准库的核心部分:容器 + 迭代器 + 算法,三者通过迭代器解耦。
什么时候用:几乎所有 C++ 程序。选对容器往往直接决定程序快不快。
std::sort、find、count_if、lower_bound 都接收迭代器区间(左闭右开)。for (const auto& x : v)。是什么:动态数组:连续内存、可自动扩容、支持随机访问 O(1)。
什么时候用:顺序存储的首选容器;读多写少、需要按下标访问时最合适。
v.push_back(x) 追加;v.size() 元素个数;v.capacity() 当前容量。v.reserve(n),避免反复扩容搬元素。是什么:有序关联容器,底层红黑树:set 是“只有键的集合”,map 是“键→值”的字典,都自动排序、去重。
什么时候用:需要按键有序遍历、需要 O(log n) 查找时。
m[key] 在键不存在时会插入默认值——只想查询用 count() 或 find()。while (std::cin >> w) { ++freq[w]; }。unordered_map / unordered_set。是什么:容器元素的“通用指针”:begin() 指向第一个元素,end() 指向最后一个元素的下一位(左闭右开)。
什么时候用:遍历容器、把区间交给算法时。
*it 取元素、++it 前进、it->成员 访问成员。end() 不指向元素,不能解引用。++it:对自定义类型少一次临时对象。是什么:容器结构改变(扩容、插入、删除)后,原来的迭代器/指针/引用可能指向已释放的内存。
什么时候用:在循环里删除或插入元素时——这是最经典的未定义行为来源。
it = v.erase(it); 接住返回值,只有没删除时才 ++it。是什么:堆结构的适配器:top() 取最值 O(1),插入/删除 O(log n)。默认是大顶堆(和 Java 默认相反)。
什么时候用:需要反复取最大值/最小值时,比如 Top K、Dijkstra。
std::priority_queue<int> pq; 大顶堆,pq.top() 是最大值。std::priority_queue<int, std::vector<int>, std::greater<int>>。是什么:两种受限的线性结构:栈后进先出(LIFO),队列先进先出(FIFO)。
什么时候用:表达式求值、括号匹配、DFS(栈)、BFS(队列)、任务排队。
std::stack<int>:push / pop / top。std::queue<int>:push / pop / front / back。是什么:节点通过指针串起来的线性结构:插入删除 O(1)(已知位置),随机访问 O(n)。
什么时候用:频繁在已知位置增删,且不想搬移元素时。
std::unique_ptr<Node> next,析构自动递归释放,不用手写 delete。是什么:一组以迭代器区间为参数的通用算法:排序、查找、计数、去重、变换……
什么时候用:能用算法库就别手写循环:短、快、不易错。
std::sort(v.begin(), v.end(), cmp);std::count_if(v.begin(), v.end(), pred); 统计满足条件的个数。是什么:就地定义的匿名函数:[](int x) { return x > 0; },可以捕获外部变量。
什么时候用:给算法传比较器/判断条件,或写一次性的小函数时。
[&] 按引用捕获、[=] 按值捕获、[x] 只捕获 x。[](const auto& a, const auto& b) { return a.score > b.score; }。auto&& self)。是什么:让编译器从初始化表达式推导类型。不是弱类型:推导结果在编译期就确定了。
什么时候用:类型名又长又啰嗦时(迭代器、结构化绑定)。
auto it = m.begin(); 比手写 std::map<std::string,int>::iterator 清爽。auto&,只读用 const auto&,别漏 &。auto x = compute(); 会让人读不懂。是什么:把 pair/tuple/结构体一次解包成多个变量:auto [a, b] = p;(C++17)。
什么时候用:遍历 map、返回多个值的函数结果时。
for (const auto& [key, value] : m) { ... } 是遍历 map 的最舒服写法。if (auto it = m.find(k); it != m.end()) { ... }。g++ -std=c++17。是什么:要求“编译期就能算出来”的常量与函数:能用在数组长度、模板参数、static_assert 里。
什么时候用:希望把计算提前到编译期、或需要真正的常量表达式时。
constexpr int square(int x) { return x * x; } 输入是编译期常量就编译期算完。static_assert(square(5) == 25); 编译期断言,不满足直接编译失败。是什么:C++11 之后的一系列改进:auto、范围 for、智能指针、lambda、constexpr、结构化绑定、移动语义……
什么时候用:新写代码都应该用现代写法,别停留在“带类的 C”。
nullptr 代替 NULL,用 enum class 代替裸枚举,用 using 代替 typedef。-std=c++17(或更高),别用十几年前的默认标准。是什么:用 throw 抛错、try/catch 捕获,把错误从发生的地方传到能处理的地方。
什么时候用:函数无法完成承诺(除零、越界、文件打不开)时;而不是用来控制正常流程。
throw std::invalid_argument("divide by zero");catch (const std::exception& e) { std::cout << e.what(); }。是什么:用 O(...) 描述数据量增大时运行时间的增长量级,是选算法和选容器的第一依据。
什么时候用:看数据范围选算法、判断会不会超时。
是什么:编译期插入检查的运行时工具,能直接报出越界、释放后使用、双重释放、整数溢出等问题。
什么时候用:调试阶段必开;写数据结构、指针相关的代码尤其重要。
g++ -std=c++17 -g -fsanitize=address,undefined -o app app.cpp。是什么:能下断点、单步执行、查看变量和调用栈的命令行调试器。
什么时候用:程序崩溃(段错误)或结果不对,靠打印排查太慢时。
g++ -std=c++17 -g -O0 -o app app.cpp。break(下断点)、run、next/step、print、bt(看调用栈)、continue、quit。bt 看调用栈,再 print 关键变量,比从头读代码快得多。是什么:用配置文件描述“源文件 + 编译选项 + 目标”,一条命令完成多文件工程的构建。
什么时候用:工程超过一个源文件,或者想把编译选项、sanitizer 开关统一管理时。
CMakeLists.txt:add_executable(app util.cpp main.cpp) + target_compile_options。cmake -S . -B build → cmake --build build → 运行。build/ 是生成物,记得写进 .gitignore。是什么:给代码写的自动检查:一条命令跑完所有用例,立刻知道有没有改坏。
什么时候用:改了代码不敢确认没影响时;写数据结构时配合随机对拍尤其有效。
是什么:每个节点最多两个孩子的结构;BST 额外保证左子树全部小于根、右子树全部大于根,中序遍历即升序。
什么时候用:需要有序且能快速查找/插入时(std::map、std::set 的底层就是平衡 BST)。
std::unique_ptr<Node> 管理左右孩子,析构自动释放。是什么:点和边组成的结构;最常用的存储是邻接表 vector<vector<int>>。
什么时候用:连通性、最短路、拓扑序、成环判断等问题。
u v,g[u].push_back(v); g[v].push_back(u);(有向图只存一边)。是什么:维护“谁和谁是一伙的”的结构:支持合并两个集合、查询是否同集合,接近 O(1)。
什么时候用:动态连通性、朋友圈、Kruskal 最小生成树。
find(x) 带路径压缩,unite(a, b) 按集合大小合并。find(i) 压平路径,再数 parent[i] == i 的个数。parent[i] = i。是什么:把数据按顺序排好。常用四种:插入、归并、快速、堆排序,都是 O(n log n) 或更好于 O(n²)。
什么时候用:需要自己实现(作业/面试)、或需要稳定排序时。
std::sort(O(n log n));想保持相等元素原顺序用 std::stable_sort。是什么:用两个下标在序列上移动,把原本 O(n²) 的暴力枚举降到 O(n)。
什么时候用:有序数组求和、去重、原地删除、回文判断。
是什么:维护一个连续区间 [l, r],右端扩张、左端收缩,一路扫完。
什么时候用:连续子数组/子串的最值或计数问题。
是什么:用哈希函数把键映射到桶,实现平均 O(1) 的插入和查找。C++ 里是 std::unordered_map / unordered_set。
什么时候用:只想快速判断“在不在”、统计频率、配对查找,不要求顺序时。
std::unordered_map<int, int> cnt; ++cnt[x]; 统计频率。count() 或 find();m[key] 会插入默认值。是什么:预先算好前缀累加 pre[i+1] = pre[i] + a[i],之后任意区间和 O(1) 得到。
什么时候用:大量区间求和查询;配合哈希还能数“和为 k 的子数组”。
pre[r+1] - pre[l]。pre[0] = 0,长度开 n+1,空区间也自然成立。是什么:在单调序列里每次砍掉一半,O(log n) 找到边界;本质是“找最小/最大满足条件的值”。
什么时候用:有序数组查找、答案具有单调性的最优化问题(二分答案)。
std::lower_bound(第一个 ≥ x)、upper_bound(第一个 > x)、binary_search(是否存在)。mid = left + (right - left) / 2 防溢出,满足条件就 right = mid。ok(x) 判断函数,再二分最小的可行解。是什么:一条路走到黑,走不通就回退。递归实现,适合连通性、枚举所有路径。
什么时候用:网格连通块、树的遍历、排列组合、判环。
是什么:一层一层向外扩散,配队列实现;第一次到达某点的层数就是最短步数。
什么时候用:无权图最短路、最少步数、层次遍历。
是什么:DFS 的一种:每步尝试所有选择,走不通就撤销选择换下一个。
什么时候用:全排列、组合、子集、八皇后、数独。
是什么:每步都选当前看起来最优的,并证明局部最优能推出全局最优。
什么时候用:区间调度、找零钱、部分最优化问题。
是什么:把大问题拆成会重复出现的小问题,用数组把子问题答案存下来避免重复计算。
什么时候用:最优值问题且子问题重叠时:爬楼梯、最大子段和、背包、编辑距离。
cur = max(a[i], cur + a[i]); best = max(best, cur);是什么:面向过程、贴近硬件的通用语言:不隐藏内存细节,也不替你管理内存。
什么时候用:想搞懂指针、内存布局、编译链接这些底层概念时;也是学 C++ 与数据结构的前置。
-std=c17;编译命令 gcc -std=c17 -Wall -Wextra -o app app.c。int main(void);没有类、没有异常、没有垃圾回收。'\0' 结尾的字符数组”,不是一种独立类型。是什么:把 C/C++ 源码编译成可执行文件的工具链;gcc 编 C,g++ 编 C++。
什么时候用:本地写 C/C++ 程序、写在线评测题目时每天都在用。
gcc -std=c17 -Wall -Wextra -o hello hello.c 编译并指定输出名。-c 只编译成目标文件(.o),-g 保留调试信息,-O2 开优化。-fsanitize=address,undefined 打开内存与未定义行为检测。gcc -o app main.c util.c。是什么:C 里在堆上申请和释放内存的一对函数:malloc 只要空间不清零,free 归还给系统。
什么时候用:数组大小要到运行时才知道、或对象的生命周期要超出函数时。
int *a = malloc(n * sizeof(int)); 申请后必须检查是否为 NULL。free(a),并把指针置空,避免悬垂指针与重复释放。calloc 会清零,realloc 用来扩容。std::vector / 智能指针(见 RAII)。是什么:以 \0 结尾的字符数组:长度靠遍历统计,容量与内容都要你自己维护。
什么时候用:用 C 处理文本时必须面对它;%s、fgets、strlen 都围绕它工作。
char buf[64]; 留出放 \0 的位置;用 %63s 限制读入长度。strlen 求长度(O(n))、strcpy 复制、strcmp 比较(不能写 ==)。fgets,注意它会保留行尾换行符。std::string,不必再操心这些。是什么:把多个字段打包成一个自定义类型的语法;结构体数组、结构体指针是链表和树的起点。
什么时候用:表示“一个学生的姓名和分数”“一个区间的左右端点”这类成组数据时。
struct Point { double x, y; }; 定义;typedef 之后可以只写 Point。p.x,指针用 p->x(等价于 (*p).x)。是什么:编译之前对源码做的纯文本处理:展开 include、替换宏、处理条件编译。
什么时候用:所有 C/C++ 程序都在用;排查重复定义、宏展开问题时要知道它的存在。
#include <stdio.h> 引入系统头文件,#include "util.h" 引入自己的头文件。#ifndef / #define / #endif 或 #pragma once)防重复包含。constexpr / inline 函数就别用宏。是什么:Java 源码编译成字节码(.class),再由 JVM 加载执行;正是这一层让 Java 跨平台。
什么时候用:理解“为什么 Java 能一次编写到处运行”“为什么需要装 JDK”时。
javac Main.java 生成 Main.class,java Main 启动 JVM 运行。是什么:写 Java 需要的开发包:包含编译器 javac、运行时 java、以及标准库。只装 JRE 只能运行、不能编译。
什么时候用:准备开发环境的第一步。
javac -version 与 java -version 一致。javac -encoding UTF-8 Main.java。public 类名一致。是什么:Java 的 String 是不可变对象;频繁拼接要用可变的 StringBuilder。
什么时候用:处理文本、循环拼接字符串时。
a.equals(b),a == b 比较的是引用。s += x(每次都新建对象),改用 sb.append(x)。length()、substring、split、join、strip()。是什么:Java 标准库的容器体系:List(有序)、Set(去重)、Map(键值)、Queue(队列),接口统一、实现可替换。
什么时候用:几乎所有需要存一组数据的地方;选错容器往往就是性能问题的根源。
ArrayList 随机访问快;HashMap 平均 O(1) 查找;TreeMap 有序 O(log n)。map.merge(key, 1, Integer::sum)。list.remove(...),用 removeIf 或迭代器。equals 与 hashCode。是什么:让容器与算法带上类型参数(List<String>),把类型错误从运行期提前到编译期。
什么时候用:使用集合、写通用工具方法时。
List<String> list = new ArrayList<>(); 声明时写类型,创建时可省略。new T[]、也不能对泛型做 instanceof。List<? extends Number> 只读、List<? super Integer> 可写。是什么:Java 把异常分成受检(必须处理或声明 throws)与非受检(RuntimeException)两类。
什么时候用:做 IO、网络、解析这些“可能失败”的操作时。
try-catch 或在方法签名上 throws。catch (IOException e),最后才用宽泛类型兜底。finally 用于必须执行的收尾。是什么:Java 的方法默认动态绑定:父类引用指向子类对象时,调用的是子类实现(多态)。
什么时候用:需要“同一段代码处理不同具体类型”时。
extends),接口可以多实现(implements)。@Override,让编译器检查签名。record。是什么:Java 16 起的不可变数据类语法:一行声明,自动生成构造器、访问器、equals、hashCode、toString。
什么时候用:只想装一组数据、不需要继承时(DTO、坐标、区间、返回值)。
record Point(int x, int y) { };访问用 p.x()(方法,不是字段)。是什么:用链式写法对集合做过滤、映射、排序、统计:list.stream().filter(...).map(...).count()。
什么时候用:处理数据集合、做统计与转换时;比手写循环更短也更易读。
filter / map / sorted 是惰性的,终止操作 count / sum / collect / forEach 才真正执行。collect(Collectors.groupingBy(f, Collectors.counting()))。是什么:动态类型、解释执行、语法极简的通用语言,标准库与第三方生态非常丰富。
什么时候用:写脚本、处理数据、做实验、搭原型时首选;也是数据科学方向的主力语言。
python hello.py;快速试验直接敲 python 进 REPL。1 + "2" 会报错,不会隐式转换。是什么:pip 是 Python 的包管理器;venv 用来给每个项目建一套独立的依赖环境。
什么时候用:安装第三方库(如 pandas)、或不同项目需要不同版本依赖时。
python -m venv .venv 创建虚拟环境;激活后 pip install pandas。.venv\Scripts\activate;macOS / Linux:source .venv/bin/activate。requirements.txt:pip freeze > requirements.txt。是什么:Python 内置的四种容器:list(有序可变)、tuple(有序不可变)、dict(键值)、set(去重)。
什么时候用:几乎所有 Python 程序都在用;选对容器代码能短一半。
append、extend、切片、sorted、sum/max/min。freq[w] = freq.get(w, 0) + 1 或 collections.Counter。set(nums),判断存在 O(1)。是什么:用一行生成列表 / 字典 / 集合:[x * x for x in range(5) if x % 2 == 0]。
什么时候用:从已有数据构造新容器时,比 for + append 更短也更快。
[f(x) for x in seq if 条件]。{name: i for i, name in enumerate(names)}。(x for x in seq) 是惰性的,适合流式处理大文件。是什么:Python 3.6 起的字符串格式化语法:f"{name} 得分 {score:.2f}"。
什么时候用:拼接字符串与数值时,比 % 和 format() 更直观。
{x:.2f} 两位小数、{x:>8} 右对齐、{x:,} 千分位。f"合计 {a + b}"。f"{value=}" 会同时打印变量名和值。是什么:用 try/except 捕获运行时错误;Python 强制你写明要捕获哪种异常类型。
什么时候用:处理外部输入、文件读写、类型转换等可能失败的操怍时。
try: ... except ValueError as e: ... 捕获具体异常。finally 一定会执行;with 用来保证资源释放(比 try/finally 更简洁)。except:,它会连键盘中断和真 bug 一起吞掉。是什么:用装饰器自动生成数据类的构造器、打印与相等判断:@dataclass class Student: name: str; score: int = 0。
什么时候用:只装数据、需要清晰的 __init__ 与 __repr__ 时。
frozen=True 可以得到不可变对象(可哈希、可做字典键)。__init__ 少写一大堆样板。是什么:Python 的数据分析主力库:用 DataFrame(表格)做读取、筛选、分组、统计与导出。
什么时候用:处理 CSV / Excel 数据、做数据清洗与统计时;博客的数据科学线也围绕它展开。
pip install pandas;读:df = pd.read_csv("a.csv")。df["score"].mean();筛选:df[df["score"] >= 60];排序:df.sort_values("score")。df.groupby("name")["score"].sum()。encoding="utf-8" 或 "gbk"。是什么:一个 .py 文件就是一个模块;用 import 引用;带 __init__.py 的目录是包。
什么时候用:把代码拆成多个文件、复用别人写的库时。
import json / from collections import Counter / import numpy as np 三种写法。if __name__ == "__main__": 让文件既能当脚本跑、又能被 import。random.py、json.py,会遮蔽标准库。