五大算法的理解
1.回溯算法:来一个简单直白的伪码
path;
for e in list{
// 前进一步
path.push(e);
{...} // 探索
// 再退回去
paht.pop(e);
}
可以看到,回溯算法和stack有很深的关系,典型的回溯算法如打印所有根节点到叶子节点的路径。
public void dfs(TreeNode node,Stack<Node> path){
// 找到一条路
if(node==null){
print(path);
return;
}
path.push(node.left);
dfs(node.left,path);
path.pop(node.left);
// 更新自己所在位置和走过的路径
path.push(node.right,path);
dfs(node.right,path);
}
还有经典的n皇后问题,回溯算法简单,但是其时间复杂度约是pow(M,n)级别, 爆炸型增长,当n很大时,往往会超时,或者栈溢出。这是在回溯算法中,没有充分使用图中的其他信息,或者按照一定的策略去搜索,比如迪杰特斯拉算法。
for 选择 in 选择列表:
# 做选择
将该选择从选择列表移除
路径.add(选择)
backtrack(路径, 选择列表)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
2.动态规划算法:也叫查表法,其实就是找到从小规模到大规模的递推公式。典型的是背包问题,看一下动态规划的简单例子:计算斐波那契数列
f(n) = f(n-1) +f(n-2)
f(5) = f(4) + f(3) ;
动态规划可以简单理解为求递推公式。在具体的程序求解问题中,可以使用函数递归,也可以使用数组迭代,优先使用迭代,这个一般会更快,并且能够处理重叠子问题。
3.分治算法:分治的思想在生活中随处可见,都是将大问题划分为小问题,比如全国行政区的划分,分子的组成等。分治的核心就是划分子问题,使划分的各个子部分不会互 相影响。 典型的如快速排序。
QUICKSORT(A, p, r)
if p < r //仅当区间长度大于1才开始排序
then q ← PARTITION(A, p, r) //选取pivot主元
QUICKSORT(A, p, q - 1) //对左子序列排序
QUICKSORT(A, q + 1, r) //对右子序列排序
PARTITION(A, p, r)
x ← A[r]
i ← p - 1
for j ← p to r - 1
do if A[j] ≤ x
then i ← i + 1
exchange A[i] ←→ A[j]
// 这个就很奇怪
exchange A[i + 1] ←→ A[r]
return i + 1
// 这个总是在pivot预留一个,用于交换,节省空间。
// 快速排序算法的思想非常简单,但是就是PARTITION方法不好理解
// do--if就是if
//思想: 使用j作为指针,去遍历所有的元素,然后将小于pivot的元素放在左边,但是为了//保证不占用空间,pivot也要又移。
参考书籍:《算法设计》
《计算机程序的构造和解释》
日进有功
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义