Files
maths-cs-ai-compendium-zh/chapter 14: data structures and algorithms/00. foundations/index.html
T

6474 lines
146 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="一本开源的直觉优先教科书,从零开始覆盖数学、计算机科学和人工智能(中文翻译版)。">
<meta name="author" content="Henry Ndubuaku (flykhan 译)">
<link rel="canonical" href="https://flykhan.github.io/maths-cs-ai-compendium-zh/chapter%2014%3A%20data%20structures%20and%20algorithms/00.%20foundations/">
<link rel="prev" href="../../chapter%2013%3A%20computing%20and%20OS/05.%20programming%20languages/">
<link rel="next" href="../01.%20arrays%20and%20hashing/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
<title>基础 - 数学、计算机科学与 AI 百科全书</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.484c7ddc.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="slate" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#o" class="md-skip">
跳转至
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="页眉">
<a href="../.." title="数学、计算机科学与 AI 百科全书" class="md-header__button md-logo" aria-label="数学、计算机科学与 AI 百科全书" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
数学、计算机科学与 AI 百科全书
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
基础
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="slate" data-md-color-accent="indigo" aria-label="切换到深色模式" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="切换到深色模式" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="slate" data-md-color-accent="indigo" aria-label="切换到浅色模式" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="切换到浅色模式" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="搜索" placeholder="搜索" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="查找">
<button type="reset" class="md-search__icon md-icon" title="清空当前内容" aria-label="清空当前内容" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
正在初始化搜索引擎
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/flykhan/maths-cs-ai-compendium-zh" title="前往仓库" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
flykhan/maths-cs-ai-compendium-zh
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="标签" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../.." class="md-tabs__link">
首页
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2001%3A%20vectors/01.%20vector%20spaces/" class="md-tabs__link">
向量
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2002%3A%20matrices/01.%20matrix%20properties/" class="md-tabs__link">
矩阵
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2003%3A%20calculus/01.%20differential%20calculus/" class="md-tabs__link">
微积分
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2004%3A%20statistics/01.%20fundamentals/" class="md-tabs__link">
统计学
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2005%3A%20probability/01.%20counting/" class="md-tabs__link">
概率论
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2006%3A%20machine%20learning/01.%20classical%20machine%20learning/" class="md-tabs__link">
机器学习
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/01.%20linguistic%20foundations/" class="md-tabs__link">
计算语言学
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2008%3A%20computer%20vision/01.%20image%20fundamentals/" class="md-tabs__link">
计算机视觉
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/01.%20digital%20signal%20processing/" class="md-tabs__link">
音频与语音
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/01.%20multimodal%20representations/" class="md-tabs__link">
多模态学习
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/01.%20perception/" class="md-tabs__link">
自主系统
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/01.%20geometric%20deep%20learning/" class="md-tabs__link">
图神经网络
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/01.%20discrete%20maths/" class="md-tabs__link">
计算机与操作系统
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
数据结构与算法
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/01.%20linux%20and%20CMD/" class="md-tabs__link">
生产级软件工程
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/00.%20why%20C%2B%2B%20and%20how%20ML%20frameworks%20work/" class="md-tabs__link">
SIMD 与 GPU 编程
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2017%3A%20AI%20inference/01.%20quantisation/" class="md-tabs__link">
AI 推理
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/01.%20systems%20design%20fundamentals/" class="md-tabs__link">
ML 系统设计
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2019%3A%20applied%20AI/01.%20AI%20for%20finance/" class="md-tabs__link">
应用 AI
</a>
</li>
<li class="md-tabs__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/01.%20quantum%20machine%20learning/" class="md-tabs__link">
前沿 AI
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="导航栏" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="数学、计算机科学与 AI 百科全书" class="md-nav__button md-logo" aria-label="数学、计算机科学与 AI 百科全书" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
数学、计算机科学与 AI 百科全书
</label>
<div class="md-nav__source">
<a href="https://github.com/flykhan/maths-cs-ai-compendium-zh" title="前往仓库" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
flykhan/maths-cs-ai-compendium-zh
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
首页
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
向量
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
向量
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2001%3A%20vectors/01.%20vector%20spaces/" class="md-nav__link">
<span class="md-ellipsis">
向量空间
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2001%3A%20vectors/02.%20vector%20properties/" class="md-nav__link">
<span class="md-ellipsis">
向量性质
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2001%3A%20vectors/03.%20norms%20and%20metrics/" class="md-nav__link">
<span class="md-ellipsis">
范数与度量
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2001%3A%20vectors/04.%20products/" class="md-nav__link">
<span class="md-ellipsis">
向量积
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2001%3A%20vectors/05.%20basis%20and%20duality/" class="md-nav__link">
<span class="md-ellipsis">
基与对偶性
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
矩阵
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
矩阵
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2002%3A%20matrices/01.%20matrix%20properties/" class="md-nav__link">
<span class="md-ellipsis">
矩阵性质
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2002%3A%20matrices/02.%20matrix%20types/" class="md-nav__link">
<span class="md-ellipsis">
矩阵类型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2002%3A%20matrices/03.%20operations/" class="md-nav__link">
<span class="md-ellipsis">
矩阵运算
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2002%3A%20matrices/04.%20linear%20transformations/" class="md-nav__link">
<span class="md-ellipsis">
线性变换
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2002%3A%20matrices/05.%20decompositions/" class="md-nav__link">
<span class="md-ellipsis">
矩阵分解
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
微积分
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
微积分
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2003%3A%20calculus/01.%20differential%20calculus/" class="md-nav__link">
<span class="md-ellipsis">
微分
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2003%3A%20calculus/02.%20integral%20calculus/" class="md-nav__link">
<span class="md-ellipsis">
积分
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2003%3A%20calculus/03.%20multivariate%20calculus/" class="md-nav__link">
<span class="md-ellipsis">
多元微积分
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2003%3A%20calculus/04.%20function%20approximation/" class="md-nav__link">
<span class="md-ellipsis">
函数逼近
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2003%3A%20calculus/05.%20optimisation/" class="md-nav__link">
<span class="md-ellipsis">
优化
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
统计学
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
统计学
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2004%3A%20statistics/01.%20fundamentals/" class="md-nav__link">
<span class="md-ellipsis">
基础
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2004%3A%20statistics/02.%20measures/" class="md-nav__link">
<span class="md-ellipsis">
统计量
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2004%3A%20statistics/03.%20sampling/" class="md-nav__link">
<span class="md-ellipsis">
抽样
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2004%3A%20statistics/04.%20hypothesis%20testing/" class="md-nav__link">
<span class="md-ellipsis">
假设检验
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2004%3A%20statistics/05.%20inference/" class="md-nav__link">
<span class="md-ellipsis">
推断
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
概率论
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
概率论
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2005%3A%20probability/01.%20counting/" class="md-nav__link">
<span class="md-ellipsis">
计数
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2005%3A%20probability/02.%20probability%20concepts/" class="md-nav__link">
<span class="md-ellipsis">
概率概念
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2005%3A%20probability/03.%20distributions/" class="md-nav__link">
<span class="md-ellipsis">
分布
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2005%3A%20probability/04.%20bayesian/" class="md-nav__link">
<span class="md-ellipsis">
贝叶斯
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2005%3A%20probability/05.%20information%20theory/" class="md-nav__link">
<span class="md-ellipsis">
信息论
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
机器学习
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
机器学习
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2006%3A%20machine%20learning/01.%20classical%20machine%20learning/" class="md-nav__link">
<span class="md-ellipsis">
经典机器学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2006%3A%20machine%20learning/02.%20gradient%20machine%20learning/" class="md-nav__link">
<span class="md-ellipsis">
梯度机器学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2006%3A%20machine%20learning/03.%20deep%20learning/" class="md-nav__link">
<span class="md-ellipsis">
深度学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2006%3A%20machine%20learning/04.%20reinforcement%20learning/" class="md-nav__link">
<span class="md-ellipsis">
强化学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2006%3A%20machine%20learning/05.%20distributed%20deep%20learning/" class="md-nav__link">
<span class="md-ellipsis">
分布式深度学习
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_8" >
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
计算语言学
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
计算语言学
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/01.%20linguistic%20foundations/" class="md-nav__link">
<span class="md-ellipsis">
语言学基础
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/02.%20text%20processing%20and%20classic%20NLP/" class="md-nav__link">
<span class="md-ellipsis">
文本处理与经典 NLP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/03.%20embeddings%20and%20sequence%20models/" class="md-nav__link">
<span class="md-ellipsis">
嵌入与序列模型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/04.%20transformers%20and%20language%20models/" class="md-nav__link">
<span class="md-ellipsis">
Transformer 与语言模型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2007%3A%20computational%20linguistics/05.%20advanced%20text%20generation/" class="md-nav__link">
<span class="md-ellipsis">
高级文本生成
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_9" >
<label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="0">
<span class="md-ellipsis">
计算机视觉
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
计算机视觉
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2008%3A%20computer%20vision/01.%20image%20fundamentals/" class="md-nav__link">
<span class="md-ellipsis">
图像基础
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2008%3A%20computer%20vision/02.%20convolutional%20networks/" class="md-nav__link">
<span class="md-ellipsis">
卷积网络
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2008%3A%20computer%20vision/03.%20object%20detection%20and%20segmentation/" class="md-nav__link">
<span class="md-ellipsis">
目标检测与分割
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2008%3A%20computer%20vision/04.%20vision%20transformers%20and%20generation/" class="md-nav__link">
<span class="md-ellipsis">
ViT 与生成模型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2008%3A%20computer%20vision/05.%20video%20and%203D%20vision/" class="md-nav__link">
<span class="md-ellipsis">
视频与 3D 视觉
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_10" >
<label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
<span class="md-ellipsis">
音频与语音
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
音频与语音
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/01.%20digital%20signal%20processing/" class="md-nav__link">
<span class="md-ellipsis">
数字信号处理
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/02.%20automatic%20speech%20recognition/" class="md-nav__link">
<span class="md-ellipsis">
自动语音识别
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/03.%20text%20to%20speech%20and%20voice/" class="md-nav__link">
<span class="md-ellipsis">
语音合成
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/04.%20speaker%20and%20audio%20analysis/" class="md-nav__link">
<span class="md-ellipsis">
说话人与音频分析
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2009%3A%20audio%20and%20speech/05.%20source%20separation%20and%20noise/" class="md-nav__link">
<span class="md-ellipsis">
源分离与降噪
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_11" >
<label class="md-nav__link" for="__nav_11" id="__nav_11_label" tabindex="0">
<span class="md-ellipsis">
多模态学习
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_11_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_11">
<span class="md-nav__icon md-icon"></span>
多模态学习
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/01.%20multimodal%20representations/" class="md-nav__link">
<span class="md-ellipsis">
多模态表征
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/02.%20vision%20language%20models/" class="md-nav__link">
<span class="md-ellipsis">
视觉语言模型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/03.%20image%20and%20video%20tokenisation/" class="md-nav__link">
<span class="md-ellipsis">
图像与视频 Token 化
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/04.%20cross-modal%20generation/" class="md-nav__link">
<span class="md-ellipsis">
跨模态生成
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2010%3A%20multimodal%20learning/05.%20unified%20multimodal%20architectures/" class="md-nav__link">
<span class="md-ellipsis">
统一多模态架构
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_12" >
<label class="md-nav__link" for="__nav_12" id="__nav_12_label" tabindex="0">
<span class="md-ellipsis">
自主系统
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_12_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_12">
<span class="md-nav__icon md-icon"></span>
自主系统
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/01.%20perception/" class="md-nav__link">
<span class="md-ellipsis">
感知
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/02.%20robot%20learning/" class="md-nav__link">
<span class="md-ellipsis">
机器人学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/03.%20vision-language-action%20models/" class="md-nav__link">
<span class="md-ellipsis">
视觉-语言-动作模型
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/04.%20self-driving/" class="md-nav__link">
<span class="md-ellipsis">
自动驾驶
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2011%3A%20autonomous%20systems/05.%20space%20and%20extreme%20robotics/" class="md-nav__link">
<span class="md-ellipsis">
太空与极端机器人
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_13" >
<label class="md-nav__link" for="__nav_13" id="__nav_13_label" tabindex="0">
<span class="md-ellipsis">
图神经网络
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_13_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_13">
<span class="md-nav__icon md-icon"></span>
图神经网络
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/01.%20geometric%20deep%20learning/" class="md-nav__link">
<span class="md-ellipsis">
几何深度学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/02.%20graph%20theory/" class="md-nav__link">
<span class="md-ellipsis">
图论
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/03.%20graph%20neural%20networks/" class="md-nav__link">
<span class="md-ellipsis">
图神经网络
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/04.%20graph%20attention%20networks/" class="md-nav__link">
<span class="md-ellipsis">
图注意力网络
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2012%3A%20graph%20neural%20networks/05.%203d%20graph%20networks/" class="md-nav__link">
<span class="md-ellipsis">
3D 图网络
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_14" >
<label class="md-nav__link" for="__nav_14" id="__nav_14_label" tabindex="0">
<span class="md-ellipsis">
计算机与操作系统
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_14_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_14">
<span class="md-nav__icon md-icon"></span>
计算机与操作系统
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/01.%20discrete%20maths/" class="md-nav__link">
<span class="md-ellipsis">
离散数学
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/02.%20computer%20architecture/" class="md-nav__link">
<span class="md-ellipsis">
计算机体系结构
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/03.%20operating%20systems/" class="md-nav__link">
<span class="md-ellipsis">
操作系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/04.%20concurrency%20and%20parallelism/" class="md-nav__link">
<span class="md-ellipsis">
并发与并行
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2013%3A%20computing%20and%20OS/05.%20programming%20languages/" class="md-nav__link">
<span class="md-ellipsis">
编程语言
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_15" checked>
<label class="md-nav__link" for="__nav_15" id="__nav_15_label" tabindex="">
<span class="md-ellipsis">
数据结构与算法
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_15_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_15">
<span class="md-nav__icon md-icon"></span>
数据结构与算法
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
基础
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
基础
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="目录">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
目录
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#_1" class="md-nav__link">
<span class="md-ellipsis">
为什么是模式,而非死记硬背
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#o_1" class="md-nav__link">
<span class="md-ellipsis">
大O表示法
</span>
</a>
<nav class="md-nav" aria-label="大O表示法">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_2" class="md-nav__link">
<span class="md-ellipsis">
增长率层级
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#o_2" class="md-nav__link">
<span class="md-ellipsis">
如何分析大O
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_3" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_4" class="md-nav__link">
<span class="md-ellipsis">
空间复杂度
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_5" class="md-nav__link">
<span class="md-ellipsis">
递归
</span>
</a>
<nav class="md-nav" aria-label="递归">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_6" class="md-nav__link">
<span class="md-ellipsis">
示例:阶乘
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_7" class="md-nav__link">
<span class="md-ellipsis">
如何以递归方式思考
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_8" class="md-nav__link">
<span class="md-ellipsis">
示例:链表上的递归
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_9" class="md-nav__link">
<span class="md-ellipsis">
示例:树上的递归
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vs" class="md-nav__link">
<span class="md-ellipsis">
递归 vs 迭代
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_10" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_11" class="md-nav__link">
<span class="md-ellipsis">
回溯
</span>
</a>
<nav class="md-nav" aria-label="回溯">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_12" class="md-nav__link">
<span class="md-ellipsis">
三个步骤
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_13" class="md-nav__link">
<span class="md-ellipsis">
何时使用回溯
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_14" class="md-nav__link">
<span class="md-ellipsis">
剪枝如何使其变快
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_15" class="md-nav__link">
<span class="md-ellipsis">
生成所有子集(最简单的回溯)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_16" class="md-nav__link">
<span class="md-ellipsis">
生成所有排列
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_17" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_18" class="md-nav__link">
<span class="md-ellipsis">
动态规划
</span>
</a>
<nav class="md-nav" aria-label="动态规划">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_19" class="md-nav__link">
<span class="md-ellipsis">
斐波那契数列的动机
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp" class="md-nav__link">
<span class="md-ellipsis">
DP 配方
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_20" class="md-nav__link">
<span class="md-ellipsis">
示例:思路过程
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp_1" class="md-nav__link">
<span class="md-ellipsis">
如何识别 DP 问题
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp_2" class="md-nav__link">
<span class="md-ellipsis">
DP 的分类
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vs_1" class="md-nav__link">
<span class="md-ellipsis">
自顶向下 vs 自底向上
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_21" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_22" class="md-nav__link">
<span class="md-ellipsis">
融会贯通
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../01.%20arrays%20and%20hashing/" class="md-nav__link">
<span class="md-ellipsis">
数组与哈希
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../02.%20linked%20lists%2C%20stacks%2C%20and%20queues/" class="md-nav__link">
<span class="md-ellipsis">
链表、栈与队列
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../03.%20trees/" class="md-nav__link">
<span class="md-ellipsis">
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../04.%20graphs/" class="md-nav__link">
<span class="md-ellipsis">
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../05.%20sorting%20and%20search/" class="md-nav__link">
<span class="md-ellipsis">
排序与搜索
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_16" >
<label class="md-nav__link" for="__nav_16" id="__nav_16_label" tabindex="0">
<span class="md-ellipsis">
生产级软件工程
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_16_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_16">
<span class="md-nav__icon md-icon"></span>
生产级软件工程
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/01.%20linux%20and%20CMD/" class="md-nav__link">
<span class="md-ellipsis">
Linux 与命令行
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/02.%20git%20and%20repository%20management/" class="md-nav__link">
<span class="md-ellipsis">
Git 与仓库管理
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/03.%20codebase%20design/" class="md-nav__link">
<span class="md-ellipsis">
代码设计
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/04.%20testing%20and%20quality%20assurance/" class="md-nav__link">
<span class="md-ellipsis">
测试与质量保障
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2015%3A%20production%20software%20engineering/05.%20deployment%20and%20devops/" class="md-nav__link">
<span class="md-ellipsis">
部署与 DevOps
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_17" >
<label class="md-nav__link" for="__nav_17" id="__nav_17_label" tabindex="0">
<span class="md-ellipsis">
SIMD 与 GPU 编程
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_17_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_17">
<span class="md-nav__icon md-icon"></span>
SIMD 与 GPU 编程
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/00.%20why%20C%2B%2B%20and%20how%20ML%20frameworks%20work/" class="md-nav__link">
<span class="md-ellipsis">
为什么是 C++ 及 ML 框架原理
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/01.%20hardware%20fundamentals/" class="md-nav__link">
<span class="md-ellipsis">
硬件基础
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/02.%20ARM%20and%20NEON/" class="md-nav__link">
<span class="md-ellipsis">
ARM 与 NEON
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/03.%20x86%20and%20AVX/" class="md-nav__link">
<span class="md-ellipsis">
x86 与 AVX
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/04.%20GPU%20architecture%20and%20CUDA/" class="md-nav__link">
<span class="md-ellipsis">
GPU 架构与 CUDA
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/05.%20triton%2C%20TPUs%20and%20pallax/" class="md-nav__link">
<span class="md-ellipsis">
Triton、TPU 与 Pallas
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/06.%20RISC-V%20and%20embedded%20systems/" class="md-nav__link">
<span class="md-ellipsis">
RISC-V 与嵌入式系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2016%3A%20SIMD%20and%20GPU%20programming/07.%20vulkan%20compute%20and%20cross-platform%20GPU/" class="md-nav__link">
<span class="md-ellipsis">
Vulkan Compute 与跨平台 GPU
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_18" >
<label class="md-nav__link" for="__nav_18" id="__nav_18_label" tabindex="0">
<span class="md-ellipsis">
AI 推理
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_18_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_18">
<span class="md-nav__icon md-icon"></span>
AI 推理
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2017%3A%20AI%20inference/01.%20quantisation/" class="md-nav__link">
<span class="md-ellipsis">
量化
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2017%3A%20AI%20inference/02.%20efficient%20architectures/" class="md-nav__link">
<span class="md-ellipsis">
高效架构
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2017%3A%20AI%20inference/03.%20serving%20and%20batching/" class="md-nav__link">
<span class="md-ellipsis">
服务与批处理
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2017%3A%20AI%20inference/04.%20edge%20inference/" class="md-nav__link">
<span class="md-ellipsis">
边缘推理
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2017%3A%20AI%20inference/05.%20scaling%20and%20deployment/" class="md-nav__link">
<span class="md-ellipsis">
扩缩与部署
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_19" >
<label class="md-nav__link" for="__nav_19" id="__nav_19_label" tabindex="0">
<span class="md-ellipsis">
ML 系统设计
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_19_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_19">
<span class="md-nav__icon md-icon"></span>
ML 系统设计
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/01.%20systems%20design%20fundamentals/" class="md-nav__link">
<span class="md-ellipsis">
系统设计基础
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/02.%20cloud%20computing/" class="md-nav__link">
<span class="md-ellipsis">
云计算
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/03.%20large%20scale%20infrastructure/" class="md-nav__link">
<span class="md-ellipsis">
大规模基础设施
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/04.%20ML%20systems%20design/" class="md-nav__link">
<span class="md-ellipsis">
ML 系统设计
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2018%3A%20ML%20systems%20design/05.%20ML%20design%20examples/" class="md-nav__link">
<span class="md-ellipsis">
ML 设计案例
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_20" >
<label class="md-nav__link" for="__nav_20" id="__nav_20_label" tabindex="0">
<span class="md-ellipsis">
应用 AI
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_20_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_20">
<span class="md-nav__icon md-icon"></span>
应用 AI
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2019%3A%20applied%20AI/01.%20AI%20for%20finance/" class="md-nav__link">
<span class="md-ellipsis">
AI 金融
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2019%3A%20applied%20AI/02.%20protein%20design/" class="md-nav__link">
<span class="md-ellipsis">
蛋白质设计
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2019%3A%20applied%20AI/03.%20drug%20discovery/" class="md-nav__link">
<span class="md-ellipsis">
药物发现
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2019%3A%20applied%20AI/04.%20agentic%20systems/" class="md-nav__link">
<span class="md-ellipsis">
智能体系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2019%3A%20applied%20AI/05.%20healthcare/" class="md-nav__link">
<span class="md-ellipsis">
医疗健康
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_21" >
<label class="md-nav__link" for="__nav_21" id="__nav_21_label" tabindex="0">
<span class="md-ellipsis">
前沿 AI
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_21_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_21">
<span class="md-nav__icon md-icon"></span>
前沿 AI
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/01.%20quantum%20machine%20learning/" class="md-nav__link">
<span class="md-ellipsis">
量子机器学习
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/02.%20neuromorphic%20computing/" class="md-nav__link">
<span class="md-ellipsis">
神经形态计算
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/03.%20datacentres%20in%20space/" class="md-nav__link">
<span class="md-ellipsis">
太空数据中心
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/04.%20decentralised%20AI/" class="md-nav__link">
<span class="md-ellipsis">
去中心化 AI
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../chapter%2020%3A%20bleeding%20edge%20AI/05.%20brain%20machine%20interfaces/" class="md-nav__link">
<span class="md-ellipsis">
脑机接口
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="目录">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
目录
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#_1" class="md-nav__link">
<span class="md-ellipsis">
为什么是模式,而非死记硬背
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#o_1" class="md-nav__link">
<span class="md-ellipsis">
大O表示法
</span>
</a>
<nav class="md-nav" aria-label="大O表示法">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_2" class="md-nav__link">
<span class="md-ellipsis">
增长率层级
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#o_2" class="md-nav__link">
<span class="md-ellipsis">
如何分析大O
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_3" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_4" class="md-nav__link">
<span class="md-ellipsis">
空间复杂度
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_5" class="md-nav__link">
<span class="md-ellipsis">
递归
</span>
</a>
<nav class="md-nav" aria-label="递归">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_6" class="md-nav__link">
<span class="md-ellipsis">
示例:阶乘
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_7" class="md-nav__link">
<span class="md-ellipsis">
如何以递归方式思考
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_8" class="md-nav__link">
<span class="md-ellipsis">
示例:链表上的递归
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_9" class="md-nav__link">
<span class="md-ellipsis">
示例:树上的递归
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vs" class="md-nav__link">
<span class="md-ellipsis">
递归 vs 迭代
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_10" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_11" class="md-nav__link">
<span class="md-ellipsis">
回溯
</span>
</a>
<nav class="md-nav" aria-label="回溯">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_12" class="md-nav__link">
<span class="md-ellipsis">
三个步骤
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_13" class="md-nav__link">
<span class="md-ellipsis">
何时使用回溯
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_14" class="md-nav__link">
<span class="md-ellipsis">
剪枝如何使其变快
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_15" class="md-nav__link">
<span class="md-ellipsis">
生成所有子集(最简单的回溯)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_16" class="md-nav__link">
<span class="md-ellipsis">
生成所有排列
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_17" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_18" class="md-nav__link">
<span class="md-ellipsis">
动态规划
</span>
</a>
<nav class="md-nav" aria-label="动态规划">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_19" class="md-nav__link">
<span class="md-ellipsis">
斐波那契数列的动机
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp" class="md-nav__link">
<span class="md-ellipsis">
DP 配方
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_20" class="md-nav__link">
<span class="md-ellipsis">
示例:思路过程
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp_1" class="md-nav__link">
<span class="md-ellipsis">
如何识别 DP 问题
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#dp_2" class="md-nav__link">
<span class="md-ellipsis">
DP 的分类
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#vs_1" class="md-nav__link">
<span class="md-ellipsis">
自顶向下 vs 自底向上
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_21" class="md-nav__link">
<span class="md-ellipsis">
常见陷阱
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_22" class="md-nav__link">
<span class="md-ellipsis">
融会贯通
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="o">基础:大O表示法、递归、回溯与动态规划<a class="headerlink" href="#o" title="Permanent link">&para;</a></h1>
<p><em>在深入学习数据结构和算法之前,你需要掌握四个基础概念:衡量效率的大O表示法、将问题分解为子问题的递归、带剪枝的穷举搜索——回溯,以及避免冗余计算的动态规划。本文件从基本原理出发逐一讲解。</em></p>
<ul>
<li>本章后续文件默认你已经熟悉了这四个概念。如果你跳过本文件,那么后面文件中的 <span class="arithmatex">\(O(n \log n)\)</span> 标注、递归树遍历、回溯模板和 DP 状态转移对你来说就会像是魔法而非工程。</li>
</ul>
<h2 id="_1">为什么是模式,而非死记硬背<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p>LeetCode、NeetCode 和 HackerRank 上有成千上万的编程题。没有人能记住全部,试图这么做是注定失败的策略。面试官不会从固定题库中选题——他们会修改、组合、伪装。背下来的"两数之和"解法,当面试官问你一个从未见过的变体时毫无用处。</p>
</li>
<li>
<p>好消息是:核心模式大约只有 <strong>15-20 种</strong>(双指针、滑动窗口、BFS/DFS、DP、回溯等)。所有问题,无论表面多新颖,最终都归结为这些模式中的一个或几个组合。面试考的不是你是否见过这道题,而是你是否能<strong>剥离上下文</strong>——故事、具体数据类型、边界情况——识别出底层的模式。</p>
</li>
<li>
<p>考虑这三个问题:</p>
<ul>
<li>"在数组中找到两个数,使其和等于一个目标值。"</li>
<li>"找到两个分子,使其结合能之和等于一个阈值。"</li>
<li>"给定一个账户余额列表,找到两个账户的余额之和等于一笔债务。"</li>
</ul>
</li>
<li>
<p>它们看起来截然不同。但它们是同一个问题:<strong>两数之和</strong>。上下文(数字、分子、账户)无关紧要。其结构是:在集合中搜索补数 → 哈希表查找。</p>
</li>
<li>
<p>这就是本章通过<strong>直觉教授模式</strong>而非通过重复教授解题方法的原因。对于每个模式,我们都会解释:</p>
<ul>
<li><strong>问题中的什么结构特征</strong>指示了这个模式(输入已排序 → 双指针;子数组约束 → 滑动窗口;最优子结构 + 重叠子问题 → DP)。</li>
<li><strong>为什么这个模式有效</strong>——数学或逻辑推理,而不仅仅是"它能给出正确答案"。</li>
<li><strong>如何适配它</strong>——通过展示简单、中等和困难变体,在这些变体中相同的核心思想应用于不同的上下文。</li>
</ul>
</li>
<li>
<p>当你深入理解<em>为什么</em>滑动窗口有效(约束的单调性意味着扩展/收缩就足够了),你就可以将其应用到任何具有该结构的问题上,即使是未曾见过的问题。当你只是背下了"无重复字符的最长子串"的代码,一旦问题发生变化,你就会束手无策。</p>
</li>
<li>
<p>实践策略:</p>
<ol>
<li><strong>学习模式</strong>(本章)。</li>
<li><strong>练习识别模式</strong>,在伪装的问题中(每个文件末尾的 NeetCode 练习题)。</li>
<li><strong>练习实现</strong>,在时间压力下。</li>
<li>面试中:阅读题目 → 剥离上下文 → 识别模式 → 实现。</li>
</ol>
</li>
</ul>
<hr />
<h2 id="o_1">大O表示法<a class="headerlink" href="#o_1" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p>当我们说一个算法"快"或"慢"时,需要一种精确的衡量方式。<strong>大O表示法</strong>描述了随着输入规模 <span class="arithmatex">\(n\)</span> 的增长,算法的运行时间(或空间使用量)如何增长,忽略了常数因子和低阶项。</p>
</li>
<li>
<p>形式化定义:<span class="arithmatex">\(f(n) = O(g(n))\)</span> 意味着存在常数 <span class="arithmatex">\(c &gt; 0\)</span><span class="arithmatex">\(n_0\)</span>,使得对所有 <span class="arithmatex">\(n \geq n_0\)</span><span class="arithmatex">\(f(n) \leq c \cdot g(n)\)</span>。通俗地说:对于大规模输入,<span class="arithmatex">\(f\)</span> 的增长速度不超过 <span class="arithmatex">\(g\)</span></p>
</li>
<li>
<p>为什么要忽略常数?因为 <span class="arithmatex">\(2n\)</span> 的算法和 <span class="arithmatex">\(5n\)</span> 的算法都是 <span class="arithmatex">\(O(n)\)</span>:它们的扩展方式相同。在更快的计算机上,常数会变,但扩展性不会。大O表示法捕捉了问题的<strong>内在</strong>难度,与硬件无关。</p>
</li>
</ul>
<h3 id="_2">增长率层级<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h3>
<ul>
<li>从最快到最慢:</li>
</ul>
<table>
<thead>
<tr>
<th>大O</th>
<th>名称</th>
<th>示例</th>
<th><span class="arithmatex">\(n = 10^6\)</span> 次操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="arithmatex">\(O(1)\)</span></td>
<td>常数级</td>
<td>数组访问、哈希查找</td>
<td>1</td>
</tr>
<tr>
<td><span class="arithmatex">\(O(\log n)\)</span></td>
<td>对数级</td>
<td>二分查找</td>
<td>20</td>
</tr>
<tr>
<td><span class="arithmatex">\(O(n)\)</span></td>
<td>线性级</td>
<td>线性扫描、单循环</td>
<td><span class="arithmatex">\(10^6\)</span></td>
</tr>
<tr>
<td><span class="arithmatex">\(O(n \log n)\)</span></td>
<td>线性对数级</td>
<td>归并排序、高效排序</td>
<td><span class="arithmatex">\(2 \times 10^7\)</span></td>
</tr>
<tr>
<td><span class="arithmatex">\(O(n^2)\)</span></td>
<td>平方级</td>
<td>嵌套循环、暴力配对</td>
<td><span class="arithmatex">\(10^{12}\)</span>(太慢)</td>
</tr>
<tr>
<td><span class="arithmatex">\(O(n^3)\)</span></td>
<td>立方级</td>
<td>三层嵌套循环、矩阵乘法</td>
<td><span class="arithmatex">\(10^{18}\)</span>(实在太慢)</td>
</tr>
<tr>
<td><span class="arithmatex">\(O(2^n)\)</span></td>
<td>指数级</td>
<td>所有子集、暴力回溯</td>
<td><span class="arithmatex">\(10^{301030}\)</span>(不可能)</td>
</tr>
<tr>
<td><span class="arithmatex">\(O(n!)\)</span></td>
<td>阶乘级</td>
<td>所有排列</td>
<td>荒谬</td>
</tr>
</tbody>
</table>
<ul>
<li>
<p><strong>经验法则</strong>:现代计算机每秒执行约 <span class="arithmatex">\(10^8\)</span><span class="arithmatex">\(10^9\)</span> 次简单操作。对于1秒的时间限制:</p>
<ul>
<li><span class="arithmatex">\(O(n)\)</span> 适用于 <span class="arithmatex">\(n \leq 10^8\)</span></li>
<li><span class="arithmatex">\(O(n \log n)\)</span> 适用于 <span class="arithmatex">\(n \leq 10^7\)</span></li>
<li><span class="arithmatex">\(O(n^2)\)</span> 适用于 <span class="arithmatex">\(n \leq 10^4\)</span></li>
<li><span class="arithmatex">\(O(2^n)\)</span> 适用于 <span class="arithmatex">\(n \leq 25\)</span></li>
</ul>
</li>
<li>
<p>这张表能立即告诉你当前方法是否足够快。如果 <span class="arithmatex">\(n = 10^5\)</span> 而你的解法是 <span class="arithmatex">\(O(n^2)\)</span>,那就是 <span class="arithmatex">\(10^{10}\)</span> 次操作——太慢了。你需要一个更好的算法。</p>
</li>
</ul>
<h3 id="o_2">如何分析大O<a class="headerlink" href="#o_2" title="Permanent link">&para;</a></h3>
<ul>
<li><strong>单循环</strong>遍历 <span class="arithmatex">\(n\)</span> 个元素:<span class="arithmatex">\(O(n)\)</span></li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">:</span> <span class="c1"># n 次迭代</span>
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a> <span class="n">total</span> <span class="o">+=</span> <span class="n">x</span> <span class="c1"># 每次迭代 O(1)</span>
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="c1"># 总计:O(n)</span>
</code></pre></div>
<ul>
<li><strong>嵌套循环</strong>:迭代次数相乘。</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># n 次迭代</span>
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># 每次 n 次迭代</span>
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a> <span class="n">process</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="c1"># O(1)</span>
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a><span class="c1"># 总计:O(n^2)</span>
</code></pre></div>
<ul>
<li><strong>每次减半的循环</strong><span class="arithmatex">\(O(\log n)\)</span>。每次迭代将问题规模减半,所以需要 <span class="arithmatex">\(\log_2 n\)</span> 次迭代。</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="n">i</span> <span class="o">=</span> <span class="n">n</span>
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a><span class="k">while</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> <span class="n">process</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a> <span class="n">i</span> <span class="o">//=</span> <span class="mi">2</span>
<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a><span class="c1"># 总计:O(log n)</span>
</code></pre></div>
<ul>
<li><strong>内循环依赖于外循环的嵌套循环</strong></li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">i</span><span class="p">):</span> <span class="c1"># j 从 0 到 i-1</span>
<a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a> <span class="n">process</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
<a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="c1"># 总计:0 + 1 + 2 + ... + (n-1) = n(n-1)/2 = O(n^2)</span>
</code></pre></div>
<ul>
<li><strong>递归</strong>:写出递推关系并求解(第13章介绍了主定理)。例如,归并排序:<span class="arithmatex">\(T(n) = 2T(n/2) + O(n) = O(n \log n)\)</span></li>
</ul>
<h3 id="_3">常见陷阱<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h3>
<ul>
<li><strong>隐藏的循环</strong>Python 中 <code>x in list</code><span class="arithmatex">\(O(n)\)</span>(线性扫描),但 <code>x in set</code><span class="arithmatex">\(O(1)\)</span>。在循环中对列表使用 <code>in</code> 会得到 <span class="arithmatex">\(O(n^2)\)</span>,而不是 <span class="arithmatex">\(O(n)\)</span></li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="c1"># 不好:O(n^2) — 对列表用 &quot;in&quot; 是 O(n)</span>
<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">:</span>
<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a> <span class="k">if</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">another_list</span><span class="p">:</span>
<a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a> <span class="n">process</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a>
<a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="c1"># 好:O(n) — 先转换为 set</span>
<a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="n">another_set</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">another_list</span><span class="p">)</span>
<a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">:</span>
<a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a> <span class="k">if</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">another_set</span><span class="p">:</span>
<a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a> <span class="n">process</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</code></pre></div>
<ul>
<li>
<p><strong>字符串拼接</strong>Python 中 <code>s += c</code> 每次都会复制整个字符串。在 <span class="arithmatex">\(n\)</span> 次迭代的循环中:<span class="arithmatex">\(O(1 + 2 + \cdots + n) = O(n^2)\)</span></p>
</li>
<li>
<p><strong>排序主导</strong>:如果你的算法先排序(<span class="arithmatex">\(O(n \log n)\)</span>)然后做线性扫描(<span class="arithmatex">\(O(n)\)</span>),总复杂度是 <span class="arithmatex">\(O(n \log n)\)</span>——排序占主导。</p>
</li>
<li>
<p><strong>平摊复杂度</strong>:某些操作偶尔很昂贵,但平摊下来很便宜。动态数组的追加操作平摊复杂度为 <span class="arithmatex">\(O(1)\)</span>,因为罕见的 <span class="arithmatex">\(O(n)\)</span> 扩容被分摊到 <span class="arithmatex">\(n\)</span> 次便宜的追加操作中。不要混淆平摊 <span class="arithmatex">\(O(1)\)</span> 和最坏情况 <span class="arithmatex">\(O(1)\)</span></p>
</li>
</ul>
<h3 id="_4">空间复杂度<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p>空间复杂度遵循同样的大O规则,只是应用于内存使用而非时间。</p>
</li>
<li>
<p><strong>原地</strong>算法使用 <span class="arithmatex">\(O(1)\)</span> 额外空间(不计输入)。快速排序是 <span class="arithmatex">\(O(\log n)\)</span> 空间(递归栈深度)。归并排序是 <span class="arithmatex">\(O(n)\)</span>(合并时使用的临时数组)。</p>
</li>
<li>
<p><strong>递归栈</strong>:每次递归调用都会使用栈空间。深度为 <span class="arithmatex">\(n\)</span> 的递归使用 <span class="arithmatex">\(O(n)\)</span> 空间,即使每次调用没有分配额外内存。这就是为什么在具有 <span class="arithmatex">\(n\)</span> 个节点的图上进行递归 DFS 使用 <span class="arithmatex">\(O(n)\)</span> 空间。</p>
</li>
<li>
<p>面试中,始终同时说明时间和空间复杂度。<span class="arithmatex">\(O(n)\)</span> 时间、<span class="arithmatex">\(O(n)\)</span> 空间的解法通常可以接受,但 <span class="arithmatex">\(O(n)\)</span> 时间、<span class="arithmatex">\(O(1)\)</span> 空间的解法更好。面试官可能会要求你优化其中一个。</p>
</li>
</ul>
<hr />
<h2 id="_5">递归<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p><strong>递归</strong>是指函数调用自身来解决同一问题的更小实例。它是处理具有递归结构的问题最自然的方式:树、嵌套数据、分治法和数学序列。</p>
</li>
<li>
<p>每个递归函数都有两部分:</p>
<ol>
<li><strong>基本情况</strong>:可以直接解决的最小的实例(无需递归)。这是递归停止的条件。</li>
<li><strong>递归情况</strong>:将问题分解为更小的子问题,递归求解,然后合并结果。</li>
</ol>
</li>
</ul>
<h3 id="_6">示例:阶乘<a class="headerlink" href="#_6" title="Permanent link">&para;</a></h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># 基本情况</span>
<a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a> <span class="k">return</span> <span class="mi">1</span>
<a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a> <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># 递归情况</span>
</code></pre></div>
<ul>
<li>
<p><code>factorial(4)</code> 的执行过程:</p>
<ul>
<li><code>factorial(4)</code> 调用 <code>factorial(3)</code></li>
<li><code>factorial(3)</code> 调用 <code>factorial(2)</code></li>
<li><code>factorial(2)</code> 调用 <code>factorial(1)</code></li>
<li><code>factorial(1)</code> 返回 <code>1</code>(基本情况)</li>
<li><code>factorial(2)</code> 返回 <code>2 * 1 = 2</code></li>
<li><code>factorial(3)</code> 返回 <code>3 * 2 = 6</code></li>
<li><code>factorial(4)</code> 返回 <code>4 * 6 = 24</code></li>
</ul>
</li>
<li>
<p>每次调用都被压入<strong>调用栈</strong>。栈一直增长直到到达基本情况,然后随着每次调用的返回而展开。如果递归太深(例如 Python 中的 <code>factorial(1000000)</code>),栈会溢出(<code>RecursionError</code>)。Python 的默认递归限制是 1000。</p>
</li>
</ul>
<h3 id="_7">如何以递归方式思考<a class="headerlink" href="#_7" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p>关键的思维转变是:<strong>信任递归</strong>。在编写递归函数时,假设递归调用已经正确返回了更小子问题的答案。你只需要:</p>
<ol>
<li>处理基本情况。</li>
<li>将问题分解为更小的部分。</li>
<li>合并结果。</li>
</ol>
</li>
<li>
<p>你不需要在脑中跟踪每一次递归调用。这就像试图通过在心里执行每次迭代来理解一个循环。相反,验证:"如果递归调用给了我更小输入的正确结果,那么我的组合步骤是否给出了完整输入的正确结果?"</p>
</li>
</ul>
<h3 id="_8">示例:链表上的递归<a class="headerlink" href="#_8" title="Permanent link">&para;</a></h3>
<ul>
<li>递归反转链表:</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">reverse</span><span class="p">(</span><span class="n">head</span><span class="p">):</span>
<a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">head</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">head</span><span class="o">.</span><span class="n">next</span><span class="p">:</span> <span class="c1"># 基本情况:0 或 1 个节点</span>
<a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> <span class="k">return</span> <span class="n">head</span>
<a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>
<a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> <span class="n">new_head</span> <span class="o">=</span> <span class="n">reverse</span><span class="p">(</span><span class="n">head</span><span class="o">.</span><span class="n">next</span><span class="p">)</span> <span class="c1"># 反转剩余部分</span>
<a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> <span class="n">head</span><span class="o">.</span><span class="n">next</span><span class="o">.</span><span class="n">next</span> <span class="o">=</span> <span class="n">head</span> <span class="c1"># 将下一个节点指回当前节点</span>
<a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a> <span class="n">head</span><span class="o">.</span><span class="n">next</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># 当前节点现在成为尾节点</span>
<a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> <span class="k">return</span> <span class="n">new_head</span>
</code></pre></div>
<ul>
<li><strong>信任递归</strong><code>reverse(head.next)</code> 正确反转了链表的剩余部分并返回新的头节点。我们只需将当前节点附加到末尾。</li>
</ul>
<h3 id="_9">示例:树上的递归<a class="headerlink" href="#_9" title="Permanent link">&para;</a></h3>
<ul>
<li>计算二叉树的高度:</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">height</span><span class="p">(</span><span class="n">root</span><span class="p">):</span>
<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">root</span><span class="p">:</span> <span class="c1"># 基本情况:空树高度为 0</span>
<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a> <span class="k">return</span> <span class="mi">0</span>
<a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a> <span class="n">left_h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">root</span><span class="o">.</span><span class="n">left</span><span class="p">)</span> <span class="c1"># 左子树高度</span>
<a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a> <span class="n">right_h</span> <span class="o">=</span> <span class="n">height</span><span class="p">(</span><span class="n">root</span><span class="o">.</span><span class="n">right</span><span class="p">)</span> <span class="c1"># 右子树高度</span>
<a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a> <span class="k">return</span> <span class="mi">1</span> <span class="o">+</span> <span class="nb">max</span><span class="p">(</span><span class="n">left_h</span><span class="p">,</span> <span class="n">right_h</span><span class="p">)</span> <span class="c1"># 当前节点增加 1 层</span>
</code></pre></div>
<ul>
<li>这种模式——"递归左子树,递归右子树,合并结果"——解决了绝大多数树的问题(见文件03)。</li>
</ul>
<h3 id="vs">递归 vs 迭代<a class="headerlink" href="#vs" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p>每个递归算法都可以转换为迭代算法(使用显式栈或循环)。迭代避免了调用栈开销和栈溢出风险。</p>
</li>
<li>
<p><strong>何时优先使用递归</strong>:问题具有自然的递归结构(树、嵌套数据、分治法)。递归解法更简洁、更易于推理。</p>
</li>
<li>
<p><strong>何时优先使用迭代</strong>:递归深度可能非常大(例如,处理包含 <span class="arithmatex">\(10^6\)</span> 个节点的链表)。迭代解法避免了栈溢出。</p>
</li>
<li>
<p><strong>尾递归</strong>:如果递归调用是函数中的最后一个操作(递归调用返回后没有后续工作),则该递归调用是"尾递归"的。某些语言(Scheme、Scala)会将尾调用优化为使用常数栈空间。Python <strong></strong>优化尾调用,因此 Python 中的尾递归仍然使用 <span class="arithmatex">\(O(n)\)</span> 栈空间。</p>
</li>
</ul>
<h3 id="_10">常见陷阱<a class="headerlink" href="#_10" title="Permanent link">&para;</a></h3>
<table>
<thead>
<tr>
<th>陷阱</th>
<th>示例</th>
<th>修复</th>
</tr>
</thead>
<tbody>
<tr>
<td>缺少基本情况</td>
<td>无限递归 → 栈溢出</td>
<td>始终定义何时停止</td>
</tr>
<tr>
<td>基本情况错误</td>
<td>递归分解中的差一错误</td>
<td>用最小的输入测试(0、1、2</td>
</tr>
<tr>
<td>问题规模未减小</td>
<td><code>f(n)</code> 调用 <code>f(n)</code> 而非 <code>f(n-1)</code></td>
<td>确保子问题严格更小</td>
</tr>
<tr>
<td>冗余计算</td>
<td>斐波那契数列:<code>f(n) = f(n-1) + f(n-2)</code> 以指数级重复计算</td>
<td>使用记忆化(→ DP</td>
</tr>
<tr>
<td>Python 递归限制</td>
<td><code>factorial(10000)</code> 崩溃</td>
<td>使用 <code>sys.setrecursionlimit</code> 或转为迭代</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_11">回溯<a class="headerlink" href="#_11" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p><strong>回溯</strong>是一种系统地探索所有可能解法的方法,通过逐步构建解并在发现部分解不可能得到有效答案时立即放弃。</p>
</li>
<li>
<p>可以把它想象成走迷宫。在每个岔路口,你选择一条路。如果碰到死胡同,你就回到上一个岔路口尝试不同的路。你不会从头开始——你<strong>回溯</strong>到最近的一个决策点。</p>
</li>
</ul>
<h3 id="_12">三个步骤<a class="headerlink" href="#_12" title="Permanent link">&para;</a></h3>
<p>每个回溯算法都遵循相同的模式:</p>
<ol>
<li><strong>选择</strong>:选择一个候选来扩展当前的部分解。</li>
<li><strong>探索</strong>:递归地尝试从这个候选构建一个完整的解。</li>
<li><strong>撤销</strong>:撤销选择(回溯)并尝试下一个候选。</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choices</span><span class="p">,</span> <span class="n">result</span><span class="p">):</span>
<a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a> <span class="k">if</span> <span class="n">is_complete</span><span class="p">(</span><span class="n">state</span><span class="p">):</span>
<a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">copy</span><span class="p">())</span>
<a id="__codelineno-8-4" name="__codelineno-8-4" href="#__codelineno-8-4"></a> <span class="k">return</span>
<a id="__codelineno-8-5" name="__codelineno-8-5" href="#__codelineno-8-5"></a>
<a id="__codelineno-8-6" name="__codelineno-8-6" href="#__codelineno-8-6"></a> <span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">choices</span><span class="p">:</span>
<a id="__codelineno-8-7" name="__codelineno-8-7" href="#__codelineno-8-7"></a> <span class="k">if</span> <span class="n">is_valid</span><span class="p">(</span><span class="n">choice</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
<a id="__codelineno-8-8" name="__codelineno-8-8" href="#__codelineno-8-8"></a> <span class="n">state</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span> <span class="c1"># 1. 选择</span>
<a id="__codelineno-8-9" name="__codelineno-8-9" href="#__codelineno-8-9"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choices</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span> <span class="c1"># 2. 探索</span>
<a id="__codelineno-8-10" name="__codelineno-8-10" href="#__codelineno-8-10"></a> <span class="n">state</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span> <span class="c1"># 3. 撤销(回溯)</span>
</code></pre></div>
<ul>
<li><strong>撤销</strong>步骤是回溯与普通递归的区别所在。没有它,状态会累积所有选择,你就无法探索替代路径。</li>
</ul>
<h3 id="_13">何时使用回溯<a class="headerlink" href="#_13" title="Permanent link">&para;</a></h3>
<ul>
<li>问题要求<strong>枚举所有有效配置</strong>:所有排列、所有子集、所有有效排列(如 N 皇后)。</li>
<li>问题要求<strong>寻找任何有效配置</strong>:数独求解、迷宫寻路。</li>
<li>搜索空间很大但可以<strong>剪枝</strong>:大多数部分解可以在完全探索之前被提前拒绝。</li>
</ul>
<h3 id="_14">剪枝如何使其变快<a class="headerlink" href="#_14" title="Permanent link">&para;</a></h3>
<ul>
<li>没有剪枝时,回溯会探索所有可能的组合——指数级时间。<strong>剪枝</strong>则提前砍掉分支:</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">choices</span><span class="p">:</span>
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_valid</span><span class="p">(</span><span class="n">choice</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a> <span class="k">continue</span> <span class="c1"># 剪枝:跳过整个子树</span>
<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a>
<a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a> <span class="n">state</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span>
<a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">choices</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
<a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a> <span class="n">state</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span>
</code></pre></div>
<ul>
<li>在 N 皇后问题(文件05)中,在放置皇后之前检查列和对角线冲突,将搜索树从 <span class="arithmatex">\(n^n\)</span> 剪枝到大约 <span class="arithmatex">\(n!\)</span> 个候选。对于 <span class="arithmatex">\(n = 8\)</span>,这是 1600 万 → 40,000。好的剪枝使指数级算法在中等规模的 <span class="arithmatex">\(n\)</span> 下变得可行。</li>
</ul>
<h3 id="_15">生成所有子集(最简单的回溯)<a class="headerlink" href="#_15" title="Permanent link">&para;</a></h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">subsets</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
<a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a> <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a>
<a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a> <span class="k">def</span><span class="w"> </span><span class="nf">backtrack</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">path</span><span class="p">[:])</span> <span class="c1"># 每个部分解都是一个有效的子集</span>
<a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a>
<a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
<a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="c1"># 选择</span>
<a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span> <span class="c1"># 探索(i+1:不允许重复使用)</span>
<a id="__codelineno-10-10" name="__codelineno-10-10" href="#__codelineno-10-10"></a> <span class="n">path</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="c1"># 撤销</span>
<a id="__codelineno-10-11" name="__codelineno-10-11" href="#__codelineno-10-11"></a>
<a id="__codelineno-10-12" name="__codelineno-10-12" href="#__codelineno-10-12"></a> <span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">[])</span>
<a id="__codelineno-10-13" name="__codelineno-10-13" href="#__codelineno-10-13"></a> <span class="k">return</span> <span class="n">result</span>
</code></pre></div>
<ul>
<li>
<p>对于 <code>[1, 2, 3]</code>,递归树:</p>
<ul>
<li><code>[]</code><code>[1]</code><code>[1,2]</code><code>[1,2,3]</code>(回溯)→ <code>[1,3]</code>(回溯)→ <code>[2]</code><code>[2,3]</code>(回溯)→ <code>[3]</code></li>
</ul>
</li>
<li>
<p>树中的每个节点是一次对 <code>backtrack</code> 的调用。每个叶子节点(以及中间节点)产生一个子集。总子集数:<span class="arithmatex">\(2^n\)</span></p>
</li>
</ul>
<h3 id="_16">生成所有排列<a class="headerlink" href="#_16" title="Permanent link">&para;</a></h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">permutations</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
<a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a> <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a>
<a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a> <span class="k">def</span><span class="w"> </span><span class="nf">backtrack</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">remaining</span><span class="p">):</span>
<a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">remaining</span><span class="p">:</span>
<a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">path</span><span class="p">[:])</span>
<a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a> <span class="k">return</span>
<a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a>
<a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">remaining</span><span class="p">)):</span>
<a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a> <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">remaining</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="c1"># 选择</span>
<a id="__codelineno-11-11" name="__codelineno-11-11" href="#__codelineno-11-11"></a> <span class="n">backtrack</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">remaining</span><span class="p">[:</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">remaining</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">:])</span> <span class="c1"># 探索</span>
<a id="__codelineno-11-12" name="__codelineno-11-12" href="#__codelineno-11-12"></a> <span class="n">path</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="c1"># 撤销</span>
<a id="__codelineno-11-13" name="__codelineno-11-13" href="#__codelineno-11-13"></a>
<a id="__codelineno-11-14" name="__codelineno-11-14" href="#__codelineno-11-14"></a> <span class="n">backtrack</span><span class="p">([],</span> <span class="n">nums</span><span class="p">)</span>
<a id="__codelineno-11-15" name="__codelineno-11-15" href="#__codelineno-11-15"></a> <span class="k">return</span> <span class="n">result</span>
</code></pre></div>
<ul>
<li>总排列数:<span class="arithmatex">\(n!\)</span>。每个排列需要 <span class="arithmatex">\(O(n)\)</span> 工作来构造 <code>remaining</code>,所以总复杂度为 <span class="arithmatex">\(O(n \cdot n!)\)</span></li>
</ul>
<h3 id="_17">常见陷阱<a class="headerlink" href="#_17" title="Permanent link">&para;</a></h3>
<table>
<thead>
<tr>
<th>陷阱</th>
<th>示例</th>
<th>修复</th>
</tr>
</thead>
<tbody>
<tr>
<td>忘记复制路径</td>
<td><code>result.append(path)</code> —— 所有条目共享同一个列表</td>
<td><code>result.append(path[:])</code><code>path.copy()</code></td>
</tr>
<tr>
<td>未回溯(撤销)</td>
<td>状态不断增长,后面的候选看到过时的状态</td>
<td>递归调用后始终执行 <code>path.pop()</code><code>state.remove()</code></td>
</tr>
<tr>
<td>循环起始位置错误</td>
<td>子集中有重复项,或排列中出现了不应有的重复使用</td>
<td>使用 <code>start</code> 参数避免重新访问之前的索引</td>
</tr>
<tr>
<td>跳过剪枝</td>
<td>探索明显无效的分支</td>
<td>在递归调用前添加 <code>if not is_valid: continue</code></td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_18">动态规划<a class="headerlink" href="#_18" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p><strong>动态规划(DP</strong>是一种优化技术,适用于相同子问题被反复求解的情况。DP 不重复计算,而是每个子问题只解一次并存储结果。</p>
</li>
<li>
<p>DP 适用于具有两个性质的问题:</p>
<ol>
<li><strong>最优子结构</strong>:最优解可以由子问题的最优解构建而成。</li>
<li><strong>重叠子问题</strong>:相同的子问题在递归中多次出现。</li>
</ol>
</li>
</ul>
<h3 id="_19">斐波那契数列的动机<a class="headerlink" href="#_19" title="Permanent link">&para;</a></h3>
<ul>
<li>朴素递归斐波那契数列:</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a> <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
<a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> <span class="k">return</span> <span class="n">n</span>
<a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a> <span class="k">return</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
</code></pre></div>
<ul>
<li>
<p>对于 <code>fib(5)</code>,递归树:</p>
<ul>
<li><code>fib(5)</code> 调用 <code>fib(4)</code><code>fib(3)</code></li>
<li><code>fib(4)</code> 调用 <code>fib(3)</code><code>fib(2)</code></li>
<li><code>fib(3)</code> 被计算了<strong>两次</strong><code>fib(2)</code> 被计算了<strong>三次</strong></li>
</ul>
</li>
<li>
<p>这是 <span class="arithmatex">\(O(2^n)\)</span>,因为树在每一层都分支,而且大多数分支重复计算相同的值。对于 <code>fib(50)</code>,需要超过 <span class="arithmatex">\(10^{15}\)</span> 次操作——不可行。</p>
</li>
<li>
<p>使用<strong>记忆化</strong>(自顶向下 DP):</p>
</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">fib_memo</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">memo</span><span class="o">=</span><span class="p">{}):</span>
<a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a> <span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">memo</span><span class="p">:</span>
<a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a> <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
<a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a> <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
<a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a> <span class="k">return</span> <span class="n">n</span>
<a id="__codelineno-13-6" name="__codelineno-13-6" href="#__codelineno-13-6"></a> <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">fib_memo</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">memo</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib_memo</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="n">memo</span><span class="p">)</span>
<a id="__codelineno-13-7" name="__codelineno-13-7" href="#__codelineno-13-7"></a> <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
</code></pre></div>
<ul>
<li>
<p>现在 <code>fib(3)</code> 只计算一次,存储起来,后续调用直接查找。总计:<span class="arithmatex">\(O(n)\)</span> 时间,<span class="arithmatex">\(O(n)\)</span> 空间。</p>
</li>
<li>
<p>使用<strong>制表法</strong>(自底向上 DP):</p>
</li>
</ul>
<div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">fib_tab</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a> <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
<a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a> <span class="k">return</span> <span class="n">n</span>
<a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a> <span class="n">dp</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a> <span class="n">dp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
<a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<a id="__codelineno-14-7" name="__codelineno-14-7" href="#__codelineno-14-7"></a> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span>
<a id="__codelineno-14-8" name="__codelineno-14-8" href="#__codelineno-14-8"></a> <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
</code></pre></div>
<ul>
<li>同样 <span class="arithmatex">\(O(n)\)</span> 时间,但自底向上构建解,无需递归。可以进一步优化到 <span class="arithmatex">\(O(1)\)</span> 空间,因为每个值只依赖于前两个值。</li>
</ul>
<h3 id="dp">DP 配方<a class="headerlink" href="#dp" title="Permanent link">&para;</a></h3>
<p>对于任何 DP 问题,遵循以下步骤:</p>
<ol>
<li>
<p><strong>定义状态</strong><code>dp[i]</code>(或 <code>dp[i][j]</code>)代表什么?这是最难的一步。状态必须捕获足够的信息以做出最优决策。</p>
</li>
<li>
<p><strong>写出递推关系</strong><code>dp[i]</code> 如何与更小的子问题关联?这是转移公式。</p>
</li>
<li>
<p><strong>确定基本情况</strong>:哪些是最小的子问题,可以直接求解?</p>
</li>
<li>
<p><strong>确定迭代顺序</strong>:哪些子问题必须先于哪些子问题求解?自底向上:按照确保依赖关系已解决的顺序迭代。自顶向下:递归会自动处理。</p>
</li>
<li>
<p><strong>优化空间</strong>(可选):如果 <code>dp[i]</code> 只依赖于前一行或前几个条目,你就不需要完整的表。</p>
</li>
</ol>
<h3 id="_20">示例:思路过程<a class="headerlink" href="#_20" title="Permanent link">&para;</a></h3>
<p><strong>问题</strong>:给定一个正整数数组,求不相邻元素的最大和(打家劫舍)。</p>
<p><strong>第1步——定义状态</strong><code>dp[i]</code> = 考虑元素 <code>nums[0..i]</code> 的最大和。</p>
<p><strong>第2步——写出递推关系</strong>:对于元素 <span class="arithmatex">\(i\)</span>,我们要么:
- 跳过它:<code>dp[i] = dp[i-1]</code>(不含元素 <span class="arithmatex">\(i\)</span> 的最佳和)。
- 取用它:<code>dp[i] = dp[i-2] + nums[i]</code>(必须跳过元素 <span class="arithmatex">\(i-1\)</span>,然后加上元素 <span class="arithmatex">\(i\)</span>)。</p>
<p>所以:<code>dp[i] = max(dp[i-1], dp[i-2] + nums[i])</code></p>
<p><strong>第3步——基本情况</strong><code>dp[0] = nums[0]</code><code>dp[1] = max(nums[0], nums[1])</code></p>
<p><strong>第4步——迭代顺序</strong>:从左到右(每个状态依赖于前两个状态)。</p>
<p><strong>第5步——空间优化</strong>:只需要最后两个值。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="k">def</span><span class="w"> </span><span class="nf">rob</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
<a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a> <span class="k">return</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a>
<a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a> <span class="n">prev2</span><span class="p">,</span> <span class="n">prev1</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">max</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">nums</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a>
<a id="__codelineno-15-7" name="__codelineno-15-7" href="#__codelineno-15-7"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
<a id="__codelineno-15-8" name="__codelineno-15-8" href="#__codelineno-15-8"></a> <span class="n">curr</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">prev1</span><span class="p">,</span> <span class="n">prev2</span> <span class="o">+</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<a id="__codelineno-15-9" name="__codelineno-15-9" href="#__codelineno-15-9"></a> <span class="n">prev2</span><span class="p">,</span> <span class="n">prev1</span> <span class="o">=</span> <span class="n">prev1</span><span class="p">,</span> <span class="n">curr</span>
<a id="__codelineno-15-10" name="__codelineno-15-10" href="#__codelineno-15-10"></a>
<a id="__codelineno-15-11" name="__codelineno-15-11" href="#__codelineno-15-11"></a> <span class="k">return</span> <span class="n">prev1</span>
</code></pre></div>
<h3 id="dp_1">如何识别 DP 问题<a class="headerlink" href="#dp_1" title="Permanent link">&para;</a></h3>
<ul>
<li>问题要求<strong>最优值</strong>(最小成本、最大利润、最长序列)或<strong>计数</strong>(方法数)。</li>
<li>问题在每一步都有<strong>选择</strong>(取/跳过、向左/向右、使用这枚硬币与否),并且整体最优答案依赖于子问题的最优答案。</li>
<li>画出递归树会显示<strong>重复的子问题</strong></li>
<li>暴力解法是指数级的,但<strong>不同的状态</strong>比递归调用少得多。</li>
</ul>
<h3 id="dp_2">DP 的分类<a class="headerlink" href="#dp_2" title="Permanent link">&para;</a></h3>
<ul>
<li>
<p><strong>1D DP</strong>:状态依赖于单个索引。示例:爬楼梯、打家劫舍、最大子数组。</p>
</li>
<li>
<p><strong>2D DP</strong>:状态依赖于两个索引。示例:最长公共子序列(<code>dp[i][j]</code> 表示字符串1的前 <span class="arithmatex">\(i\)</span> 个字符和字符串2的前 <span class="arithmatex">\(j\)</span> 个字符)、编辑距离、网格路径问题。</p>
</li>
<li>
<p><strong>区间 DP</strong>:状态是一个区间 <code>dp[i][j]</code>,表示 <code>arr[i..j]</code> 上的子问题。示例:矩阵链乘法、戳气球。</p>
</li>
<li>
<p><strong>背包 DP</strong>:状态是物品索引和容量。示例:0/1 背包、零钱兑换、子集和。</p>
</li>
<li>
<p><strong>位掩码 DP</strong>:状态包含一个位掩码,表示哪些元素已被使用。示例:旅行商问题、分配问题。状态空间为 <span class="arithmatex">\(O(2^n \cdot n)\)</span>,对于 <span class="arithmatex">\(n \leq 20\)</span> 可行。</p>
</li>
</ul>
<h3 id="vs_1">自顶向下 vs 自底向上<a class="headerlink" href="#vs_1" title="Permanent link">&para;</a></h3>
<table>
<thead>
<tr>
<th></th>
<th>自顶向下(记忆化)</th>
<th>自底向上(制表法)</th>
</tr>
</thead>
<tbody>
<tr>
<td>实现</td>
<td>递归 + 缓存</td>
<td>迭代 + 表</td>
</tr>
<tr>
<td>计算</td>
<td>只计算实际需要的子问题</td>
<td>计算直到目标的所有子问题</td>
</tr>
<tr>
<td>栈溢出风险</td>
<td>有(深度递归)</td>
<td></td>
</tr>
<tr>
<td>空间优化</td>
<td>较难</td>
<td>较易(使用滚动数组)</td>
</tr>
<tr>
<td>编码难度</td>
<td>通常更自然(写递归,加缓存)</td>
<td>需要考虑迭代顺序</td>
</tr>
</tbody>
</table>
<ul>
<li>在面试中,自顶向下通常编码更快。在生产环境中,自底向上通常更受青睐(无递归开销,缓存行为更好)。</li>
</ul>
<h3 id="_21">常见陷阱<a class="headerlink" href="#_21" title="Permanent link">&para;</a></h3>
<table>
<thead>
<tr>
<th>陷阱</th>
<th>示例</th>
<th>修复</th>
</tr>
</thead>
<tbody>
<tr>
<td>状态定义错误</td>
<td><code>dp[i]</code> 没有捕获足够信息来做决策</td>
<td>增加维度(例如用 <code>dp[i][j]</code> 代替 <code>dp[i]</code></td>
</tr>
<tr>
<td>缺少基本情况</td>
<td><code>dp[0]</code> 错误 → 所有后续值都错</td>
<td>手动验证基本情况</td>
</tr>
<tr>
<td>迭代顺序错误</td>
<td>在依赖关系未解决之前计算 <code>dp[i]</code></td>
<td>画出依赖箭头并相应迭代</td>
</tr>
<tr>
<td>未正确初始化 <code>dp</code></td>
<td>用 0 而应该用无穷大(求最小值时)</td>
<td>最小化用 <code>float('inf')</code>,最大化用 <code>float('-inf')</code></td>
</tr>
<tr>
<td>忘记考虑"跳过"选项</td>
<td>总是取当前元素</td>
<td>递推关系通常有 <code>max(take, skip)</code></td>
</tr>
<tr>
<td>可变的默认参数</td>
<td><code>def f(memo={})</code> 在调用间共享缓存</td>
<td><code>def f(memo=None): if memo is None: memo = {}</code></td>
</tr>
<tr>
<td>2D DP 中的差一错误</td>
<td><code>dp</code> 是 1-indexed 时访问 <code>text1[i]</code></td>
<td><code>dp</code> 大小为 <code>(m+1) x (n+1)</code>,访问 <code>text1[i-1]</code></td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_22">融会贯通<a class="headerlink" href="#_22" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p>这四个概念构成一个递进关系:</p>
<ol>
<li><strong>大O表示法</strong>告诉你一个方法是否足够快。</li>
<li><strong>递归</strong>将问题分解为子问题。</li>
<li><strong>回溯</strong>是递归 + 选择 + 撤销,用于穷举搜索。</li>
<li><strong>DP</strong>是递归 + 缓存,用于具有重叠子问题的优化。</li>
</ol>
</li>
<li>
<p>当你遇到一个新问题时:</p>
<ul>
<li>估计输入规模 <span class="arithmatex">\(n\)</span>。什么样的 Big O 是可接受的?</li>
<li>如果暴力解法是指数级的,且问题要求枚举/寻找配置:<strong>回溯</strong>(配合剪枝使其可行)。</li>
<li>如果暴力解法是指数级的,且问题要求最优值或计数,并且你看到重叠子问题:<strong>DP</strong></li>
<li>如果问题具有减半搜索空间的结构:<strong>二分查找</strong><strong>分治法</strong></li>
<li>如果问题涉及序列且有子数组约束:<strong>滑动窗口</strong><strong>双指针</strong></li>
<li>如果问题需要快速查找:<strong>哈希表</strong></li>
</ul>
</li>
</ul>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
回到页面顶部
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../../chapter%2013%3A%20computing%20and%20OS/05.%20programming%20languages/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 编程语言">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
上一页
</span>
<div class="md-ellipsis">
编程语言
</div>
</div>
</a>
<a href="../01.%20arrays%20and%20hashing/" class="md-footer__link md-footer__link--next" aria-label="下一页: 数组与哈希">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
数组与哈希
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://github.com/flykhan/maths-cs-ai-compendium-zh" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"annotate": null, "base": "../..", "features": ["navigation.tabs", "navigation.sections", "navigation.expand", "navigation.top", "navigation.footer", "search.suggest", "search.highlight", "content.code.copy", "toc.follow"], "search": "../../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "\u5df2\u590d\u5236", "clipboard.copy": "\u590d\u5236", "search.result.more.one": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.more.other": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 # \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.none": "\u6ca1\u6709\u627e\u5230\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.one": "\u627e\u5230 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.other": "# \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.placeholder": "\u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22", "search.result.term.missing": "\u7f3a\u5c11", "select.version": "\u9009\u62e9\u5f53\u524d\u7248\u672c"}, "version": null}</script>
<script src="../../assets/javascripts/bundle.79ae519e.min.js"></script>
<script src="../../javascripts/mathjax.js"></script>
<script src="https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js"></script>
</body>
</html>