[Algorithm] 算法训练 202609
Categories Algorithms
Tags
20260902
- 59. 螺旋矩阵 II 左开右闭
- 58. 区间和(第九期模拟笔试) 熟悉一下 Go 中标准输入输出的写法:
package main import ( "bufio" "fmt" "os" ) func main() { in := bufio.NewReader(os.Stdin) out := bufio.NewWriter(os.Stdout) defer out.Flush() var n int fmt.Fscan(in, &n) ... // 连续读入 for { var a, b int if _, err := fmt.Fscan(in, &a, &b); err != nil { break } ... fmt.Fprintln(out, arr[b] - arr[a - 1]) } }
20260903
- 44. 开发商购买土地(第五期模拟笔试)
slices.Copymin()max()(Go 1.21)copy(dst, src)math.MaxInt自己写abs函数- 对于
min()max(),无类型常量可以相互运算,结果可以近似理解为x + y。但是例如float64int之间不可以运算。string之间可以运算(字典序),但是slices,map都不可以。 slices.Clone()min()max()都是 Go 1.21 后才加入的,math.MaxInt是 Go 1.17 才加入的mmin = int(^uint(0) >> 1) // 无符号数逻辑右移- Go 中左移右移规则与 C 基本一致,但是
- 允许移位次数 >= 位宽(C 中 Undefined,编译器可以假设不会出现这种情况并且对这种情况进行优化)
- 不允许右操作数为负数
- 常量为负:编译错误
- 运行时计算出来的为负:runtime panic
- 负的有符号数右移作算数右移(C 中 Implementation-define,GCC/Clang/MSVC 都是算数右移)
- 左移发生溢出,有具体整数类型直接按照位宽截断(C 中 Undefined,编译器可以假设不会出现这种情况并且进行优化)
- 无类型整数常量没有固定的位宽,在编译器可以使用任意精度:
const x = 1 << 100
- 无类型整数常量没有固定的位宽,在编译器可以使用任意精度:
- Go 中的
make([]T, n)会创造 n 个元素,每个元素为T的零值- 值
- 所有整数:
0 - 所有浮点:
0 complex64/128(复数,实部和虚部都是float32/64):0+0ivar z complex128 = 3 + 4i z := complex(3.0, 4.0) fmt.Println(real(z)) // 3 fmt.Println(imag(z)) // 4bool:falsestring:""
- 所有整数:
- 引用/指针:
nil*T[]Tmapchanfuncinterface
- 数组和
struct内部成员递归取零值var a [3]int // [0, 0, 0] type Person struct { age int // 0 name string // "" ok bool // false } - interface typed nil !=
nil(BUT why???)
- 值
- 对于
- 203. 移除链表元素 Go 中不需要手动
free() - 206. 反转链表 递归不会做了呀…双指针也忘记了
- 142. 环形链表 II 主要想一下数学推导如何来的
20260904
对 Golang 的语法太不熟悉了。。。基本上都是语法上的问题
- 242. 有效的字母异位词 分清
arrayslice的区别;unicode提供转换、判断大小写的方法(参数是rune);strings提供转换大小写的方法 - 349. 两个数组的交集 模拟
set,一个和两个两种方法 - 1. 两数之和 为啥会做错?
- 454. 四数相加 II e…
- 18. 四数之和 去重做法;
slices.Sort()
20260905
- 541. 反转字符串 II
slices.Reverse();显式类型转换 - 54. 替换数字(第八期模拟笔试)
slices.Clone()里的参数必须是slice,而copy(dst, src)中,dst如果是[]byte/,[]runesrc可以是string- 对于标准输入,如果想要读入
string,可以用[]byte;但是如果想要用[]rune,需要:var s string fmt.Fscan(in, &s) s1 := []rune(s) - 对于这题还是不用
runeunicode.IsDigit()了… byte == uint8表示一个字节;rune == int32表示一个 Unicode 码点string是不可变字节序列,s[i]取出来的是byte,但是遍历s取出来的是rune
这里的s := "a你好" for i, r := range s { fmt.Fprintln(out, i, r) }i只有可能是0 1 4(表示的是 UTF-8 字节序列的起始下标,中文占 3 bytes)
- 151. 反转字符串中的单词 库函数和手写两种方法
strings.Join([]string, " ")strings.Fields()- 几种修改 len or cap 的操作(通常 resize 用第一个):
s = s[:n] // len == n s = s[:n:n] // len == cap == n s = slices.Clip(s) // 同上 s = slices.Clone(s) // 产生新的底层数组
20260908
- 55. 右旋字符串(第八期模拟笔试) OJ 的 Go 版本太老了…
- 28. 找出字符串中第一个匹配项的下标 库函数和 KMP
strings.Index()strings.LastIndex()返回字节下标,找不到返回-1;strings.Contains()
20260909
- 459. 重复的子字符串 暴力;去头去尾(充分性+必要性);KMP(充分性+必要性)
- 232. 用栈实现队列 Implement stack or queue using slice;自动解引用和取地址(方法调用和字段访问);
nil slice可以append() - 20. 有效的括号 untyped rune constant 可以适配比较对象的类型;Go 不支持隐式类型转换
- 150. 逆波兰表达式求值 strconv package
- 49. 字母异位词分组 key 是?
- 128. 最长连续序列 空间换时间,不是开头就跳过,是开头找最远
- 1206. 设计跳表 e啊aa。。。。。。
- 从高往低遍历
getLv()注意边界updates什么时候需要初始化
20260910
- 11. 盛最多水的容器 Two Pointers Greedy
- 496. 下一个更大元素 I 单调栈 用map映射idx和val
- 503. 下一个更大元素 II
- 42. 接雨水 eaaaaaaaaaa 单调栈 双指针 前后缀最大值 三种方法
- 84. 柱状图中最大的矩形 双指针 单调栈 两种方法
- 展开 Slice:
a... copy()对重叠安全,例如可以copy(height[1:], height)
- 展开 Slice:
20260913
- 3. 无重复字符的最长子串 一次移动一次/移动到最后一次出现的位置
- 239. 滑动窗口最大值 单调队列
- 347. 前 K 个高频元素
container/heap
20260914
- 101. 对称二叉树 递归/迭代
- 111. 二叉树的最小深度 迭代法,有别于最大深度,最小深度要求的是根结点到最近的叶子节点的距离,因此若一个节点不是叶子节点但其中一个子节点为空,只能返回
1 + depth。实际上求的也是高度 - 559. N 叉树的最大深度 迭代 语法问题。。。返回数组的最大值或者遍历的过程中记录最大值
max()是语言内置函数,不能传入vs...
- 104. 二叉树的最大深度 可以求高度/用“深度”回溯,函数闭包的写法
- 110. 平衡二叉树 求高度
- 257. 二叉树的所有路径
20260915
- 404. 左叶子之和 递归 前中后序 层序遍历 都可以
- 513. 找树左下角的值 递归
- 113. 路径总和 II 迭代法:注意
slices的特性 两种递归法
构造二叉树类的题目一般都用递归不用迭代,比较简单 - 617. 合并二叉树 迭代法
二叉搜索树的题无非两种做法:中序遍历(迭代和递归都可以,较为简单)求出数组再操作;中序遍历记录上一次遍历的指针或者值进行比较。实则都是利用其中序有序的特点 - 98. 验证二叉搜索树
- 530. 二叉搜索树的最小绝对差
- 501. 二叉搜索树中的众数 脑子做出问题了…
20260916
- 236. 二叉树的最近公共祖先 回溯法
- 235. 二叉搜索树的最近公共祖先 回溯 迭代 利用有序性 不用stack模拟
- 450. 删除二叉搜索树中的节点 回溯 迭代 重要在于左右都不为空如何删除
- 669. 修剪二叉搜索树 迭代法
- 1038. 从二叉搜索树到更大和树 回溯法
- 438. 找到字符串中所有字母异位词 哈希 滑动窗口
[n]int类型可比 - 560. 和为 K 的子数组 前缀和更好的定义(也可以用sum代替);哈希(两数之和)
20260917
回溯法:限制/不限制数量,重复/不重复 收集答案时的数组一定要拷贝
- 77. 组合 剪枝
- 39. 组合总和 如何剪枝
- 40. 组合总和 II 去重,很像四数之和
- 131. 分割回文串 dp回文
- 93. 复原 IP 地址
对于组合问题的去重,如果可以sort,那就直接用四数之和一样的做法(或者used数组);如果不能sort就用set,并且set一定得在每一层初始化(树层去重,值作为key)。前者也可以用set,但是一定要sort再使用 - 491. 非递减子序列
used数组(本质就是set) / set 不可以sort - 40. 组合总和 II 去重不能用set(除非sort)
对于排列问题的去重,used数组一定要在层外初始化(树枝去重,下标作为key) - 46. 全排列 因为不重复,所以可以用值作为key
- 47. 全排列 II 和上一题相比可以重复,所以不可以用值作为set的key,必须要是下标(否则会漏情况);要排序,因为也要做树层去重
所以树层去重如果要用used数组一定要排序,不排序只能用set
AI总结一下:
1. 先问:为什么会重复?
2. 如果是“同一条路径不能重复使用同一个元素”
→ 树枝限制
→ used[index]
3. 如果是“同一层不能用相同的值开重复分支”
→ 树层去重
能排序:
→ sort
→ 利用相邻相同元素去重
不能排序:
→ 每层 set / used[value]
4. 如果是排列:
→ 每层都从 0 开始枚举
→ 往往需要 used[index] 判断当前路径哪些元素用过
5. 如果是组合:
→ 有 startIndex
→ 下一层从 i+1 开始
→ startIndex 本身就限制了元素不能回头使用
最后一点 startIndex 本身就限制了元素不能回头使用 我的理解如下:
- 如果是组合问题,如果
i == index,即使nums[i] == nums[i - 1],也并不说明是本层重复使用了,而肯定是上一层使用了,所以说不需要用!used[i - 1](used为true表示上一层用过;为false说明本层用过,因为i是从左往右遍历的,既然上一层没用过那当前数的前面肯定本层用过了) 来判断是否是树层使用过了。 - 但是排列问题总是从 0 开始遍历,数组靠后的数都有可能是上一层,所以必须要用
!used[i - 1] - 51. N 皇后 模拟
- 37. 解数独
20260918
- 376. 摆动序列 贪心 dp
- 53. 最大子数组和
- 122. 买卖股票的最佳时机 II 贪心
- 55. 跳跃游戏 贪心
20260920
- 45. 跳跃游戏 II 贪心
- 1005. K 次取反后最大化的数组和
slices.SortFunc(s, cmp) - 134. 加油站 全局最优/贪心
- 135. 分发糖果 实则好理解
- 406. 根据身高重建队列 排序 贪心
- 452. 用最少数量的箭引爆气球 重叠
- 435. 无重叠区间 同上
- 56. 合并区间 同上 ac
- 763. 划分字母区间
- 数组/切片的下标允许任意整数类型,但是
map[int]int的key不行
- 数组/切片的下标允许任意整数类型,但是
- 738. 单调递增的数字
- 968. 监控二叉树 递归,返回值代表状态
下面开始DP - 343. 整数拆分 递推
- 494. 目标和 初始化和临界条件
- 377. 组合总和 Ⅳ 遍历顺序 求排列
- 322. 零钱兑换 求最少数量,经常要考虑不可达的情况…最好是比极端值多或者少一点
- 139. 单词拆分 有排列之感
- 213. 打家劫舍 II 成环了
- 337. 打家劫舍 III 树形DP
- 121. 买卖股票的最佳时机 贪心 DP有别于可以买卖多次
- 188. 买卖股票的最佳时机 IV 并非不可达,同日买卖即可
- 309. 买卖股票的最佳时机含冷冻期 状态转移 要不重不漏
20260921
关键看dp数组定义是以i-1结尾还是区间…
- 718. 最长重复子数组 状态压缩,从二维dp修改
- 1143. 最长公共子序列 注意dp数组定义和状态转移
- 53. 最大子数组和 贪心
- 392. 判断子序列 可以不用LCS,但此时dp数组定义不同:t的结尾不允许不选,但是s的结尾一定要选。这里代码随想录的题解写的非常不清楚。。。/双指针
- 115. 不同的子序列 注意初始化
其实就是看s或者t能不能删除吧,如果需要t匹配s,那么t肯定不能删除。感觉都考虑范围,然后考虑删除的次数比较合理呢
| 题目 | s |
t |
求什么 |
|---|---|---|---|
| 1143 LCS | 可以不选 | 可以不选 | 最长长度 |
| 392 判断子序列 | 必须全部匹配 | 可以不选 | 能否匹配 |
| 115 不同子序列 | 可以不选 | 必须全部匹配 | 匹配方案数 |
- 583. 两个字符串的删除操作 两种方法,第二种可以LCS
- 647. 回文子串 dp数组的定义:是否是回文/双指针
- 516. 最长回文子序列 注意是序列,dp数组的定义:长度
- 200. 岛屿数量 bfs/dfs
- 994. 腐烂的橘子 多源bfs
- 207. 课程表 邻接表 入度 拓扑排序
- 208. 实现 Trie (前缀树) 26叉树
20260924
- 49. 字母异位词分组 不排序
- 128. 最长连续序列
- 15. 三数之和 去重
Page views: Loading... · Visitors: Loading...
Except where otherwise noted, original content on this site is dedicated to the public domain under CC0 1.0.
Powered by Hexo & Theme mdsuper
沪ICP备2026040813号