Lazy loaded image
技术分享
5️⃣more about me 第一篇空白文章
Words 2901Read Time 8 min
2021-7-2
2025-9-22
type
status
date
slug
summary
tags
category
icon
password

Algorithm

 

Complexity

notion image
 

Binary Search

🔥
The idea of binary search is very straight forward, but the details may drive people crazy.
Leetcode 69 Sqrt(x) // 这个题其实就相当于找比这个数小的,最大的一个
找到等于target,或者必 target 小的数中最大的一个
找小的
做二分查找的一些技巧:
  • 把每种情况,== > < 都写的特别清楚,必须要把各种情况清晰
  • 先排除一些 corner case
    • 比如我们很清楚,0 1 的 sqrt 就是本身,那么直接开始的时候判断一下,返回
对于本题,如果细节不太清晰,我的一个小技巧是,用个 third variable, 来记录可能的答案,记录完之后直接往下走,左右都没有停留。不是特别好看但能够解决问题。
正式的写法:
  • 首先我们不能陷入无尽的循环,这是很重要的一件事,既然不能无限循环,那么必然小的一边也要走,不能有 left = mid,这就是纯纯无限循环。
  • 既然这样一直往下走了,那么我们可以知道 left 一定不会是最后的答案,因为它总是往下走,可能把正确答案都走过了,所以最后应该返回 high 是答案。
 
另一种经典情况,找比这个数大的,最小的一个:
找大的一个,那么碰到大的情况,就可以 high = mid,因为 mid 总是向 left 走,最后 left 一定错出,然后 high 是可能的答案
 
无脑用第三变量!记录可能答案,两头都往下走。
 
 
Template
If we do:
 
 
Leetcode 540
分奇偶
学到一个技巧,^ 1,会把偶数变成加一的数,把奇数变成减一的数,图论中有更多的应用
或者分奇偶的方式处理:
 

DFS and BFS (Search)

Back Track

Back Track Template

labuladong back track
回溯算法解题套路框架
通知: 数据结构精品课 已更新到 V2.1,手把手刷二叉树系列课程 上线,第 16 期刷题打卡开始报名。 读完本文,你不仅学会了算法套路,还可以顺便解决如下题目: ---- 本文有视频版: 回溯算法框架套路详解 。建议关注我的 B 站账号,我会用视频领读的方式带大家学习那些稍有难度的算法技巧。 这篇文章是很久之前的一篇 回溯算法详解 的进阶版,之前那篇不够清楚,就不必看了,看这篇就行。把框架给你讲清楚,你会发现回溯算法问题都是一个套路。 本文解决几个问题: 回溯算法是什么?解决回溯算法相关的问题有什么技巧?如何学习回溯算法?回溯算法代码是否有规律可循? 其实回溯算法和我们常说的 DFS 算法非常类似,本质上就是一种暴力穷举算法。回溯算法和 DFS 算法的细微差别是: 回溯算法是在遍历「树枝」,DFS 算法是在遍历「节点」,本文就是简单提一下,等你看到后文 图论算法基础 时就能深刻理解这句话的含义了。 废话不多说,直接上回溯算法框架,解决一个回溯问题,实际上就是一个决策树的遍历过程,站在回溯树的一个节点上,你只需要思考 3 个问题: 1、路径:也就是已经做出的选择。 2、选择列表:也就是你当前可以做的选择。 3、结束条件:也就是到达决策树底层,无法再做选择的条件。 如果你不理解这三个词语的解释,没关系,我们后面会用「全排列」和「N 皇后问题」这两个经典的回溯算法问题来帮你理解这些词语是什么意思,现在你先留着印象。 代码方面,回溯算法的框架: 其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」 ,特别简单。 什么叫做选择和撤销选择呢,这个框架的底层原理是什么呢?下面我们就通过「全排列」这个问题来解开之前的疑惑,详细探究一下其中的奥妙! 力扣第 46 题「 全排列」就是给你输入一个数组 nums ,让你返回这些数字的全排列。 PS:我们这次讨论的全排列问题不包含重复的数字,包含重复数字的扩展场景我在后文 回溯算法秒杀排列组合子集的九种题型 中讲解。 我们在高中的时候就做过排列组合的数学题,我们也知道 n 个不重复的数,全排列共有 n!
回溯算法解题套路框架
Template
labuladong 把所有回溯都看成树的问题🌲
既然看成树🌲,有时候就需要剪枝,对付一些有重复的情况
例题:
 

排列-组合-子集 问题 → back track

回溯算法秒杀所有排列-组合-子集问题
通知: 数据结构精品课 已更新到 V2.1,手把手刷二叉树系列课程 上线,第 16 期刷题打卡开始报名。 读完本文,你不仅学会了算法套路,还可以顺便解决如下题目: ---- 本文有视频版: 回溯算法秒杀所有排列/组合/子集问题 。建议关注我的 B 站账号,我会用视频领读的方式带大家学习那些稍有难度的算法技巧。 虽然排列、组合、子集系列问题是高中就学过的,但如果想编写算法解决它们,还是非常考验计算机思维的,本文就讲讲编程解决这几个问题的核心思路,以后再有什么变体,你也能手到擒来,以不变应万变。 无论是排列、组合还是子集问题,简单说无非就是让你从序列 nums 中以给定规则取若干元素,主要有以下几种变体: 形式一、元素无重不可复选,即 nums 中的元素都是唯一的,每个元素最多只能被使用一次,这也是最基本的形式。 以组合为例,如果输入 nums = [2,3,6,7],和为 7 的组合应该只有 [7] 。 形式二、元素可重不可复选,即 nums 中的元素可以存在重复,每个元素最多只能被使用一次。 形式三、元素无重可复选,即 nums 中的元素都是唯一的,每个元素可以被使用若干次。 当然,也可以说有第四种形式,即元素可重可复选。但既然元素可复选,那又何必存在重复元素呢?元素去重之后就等同于形式三,所以这种情况不用考虑。 上面用组合问题举的例子,但排列、组合、子集问题都可以有这三种基本形式,所以共有 9 种变化。 除此之外,题目也可以再添加各种限制条件,比如让你求和为 target 且元素个数为 k 的组合,那这么一来又可以衍生出一堆变体,怪不得面试笔试中经常考到排列组合这种基本题型。 但无论形式怎么变化,其本质就是穷举所有解,而这些解呈现树形结构,所以合理使用回溯算法框架,稍改代码框架即可把这些问题一网打尽 。 具体来说,你需要先阅读并理解前文 回溯算法核心套路 ,然后记住如下子集问题和排列问题的回溯树,就可以解决所有排列组合子集相关的问题: 为什么只要记住这两种树形结构就能解决所有相关问题呢?
回溯算法秒杀所有排列-组合-子集问题
涉及到给的数组里有重复的,可能需要剪枝
一些排列的题目,所有元素都要用上,可能需要多加一个 boolean[] used,来记录那些出现过
例题:全排序
 
39
用回溯做的,回溯最熟,剪枝(这题必须剪枝,不然有重复),然后找到答案记录下来即可
还有一种代码更简单的写法,但这种写法每次都生成新数组,时间和空间复杂度更高(仅仅看起来简单而已),其实实际写的时候,还是上面的写的顺利,符合那个做选择,撤销选择的逻辑
 
 

Two pointers

 

Tree

很多东西都可以看成树:链表,回溯,快排,merge sorted list
 
前中后序的理解:
 
在树的题目大体有两种思路:
  1. 遍历,配合外部变量
  1. 分解问题,只专注这一个点如何操作
分解问题的思想,例题:
notion image
notion image
 
 
 
层次遍历 Order traverse
notion image
 
 
 

Dynamic Programming 动态规划

Cyc dp
  • Cyc 自底向上的写法比较多
  • 01 背包的问题重点看
 
  • 自己写了一些自顶向下的方法(直接无脑递归)
  • 01 背包学 Cyc
 
任何题目,都推荐先上来 brute force,暴力递归解决,然后再优化
 

01 bag

🔥
从一堆东西里拿一部分东西,让这些有一个特定的和,或者让这些拿出来的东西特定的变成什么样,这就叫 01 背包!
  • 东西只能拿一次
    • dp table
      • dp[i] 就表示 target 是 i 的时候答案是多少
      • 长度是 target + 1,dp[target] 是答案
    • 两个 for
      • 外层的循环 num
        • 外层循环 num 就是说,每循环一个 num,都更新一轮 dp
      • 内层的循环 target
        • 从大到小循环,这样才说明这个物品只用了一次,不重复用
    • 时间复杂度就是 O(nm)
 
如果是回溯的方法(看成树,树的每个节点都可能是答案),遍历所有的可能的拿的组合,那么时间复杂就是 O(2^n) exponential 时间复杂度是指数型的,而 dp 的是平方的,一般情况下,当然是平方的 dp 好,但也有例外,如果 m 特别特别大,那么可能指数型的反而更好
 
上一篇
示例文章
下一篇
示例文章