Skip to content

Commit 1791224

Browse files
committed
feat: add bit&setment_tree
1 parent 79c6d87 commit 1791224

19 files changed

+690
-104
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.idea/leetcode.iml

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 95 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,134 @@
1-
# LEETCODE
1+
# LEETCODE 刷题笔记
22

3-
- 做题换算 难 = 2 * 中等 == 4 * 简单
4-
- 做到需要收费的时候每天 4 题及其以下
5-
- 变量定义域的使用按照C语言使用(更加规范)
6-
- 编写算法不仅需要保证性能,也需要保证代码的可读性
7-
- 160题附近开始收费,此时已经做完所有的数据结构一遍了(似乎还差图,但是树也是特殊的图)
8-
- 本人算法实现规则:
9-
- 时间复杂度需要达到最低
10-
- 空间复杂度不超过O(n)即可,对于空间复杂度的要求非必要不降低到O(1)
11-
- 本人变量命名
12-
- des_XXX 表示目标值
13-
- rec_f 表示递归/迭代函数
3+
## 一、刷题原则与规范
144

15-
## 数据结构&算法基础
5+
### 1. 刷题规则
6+
- 难度换算: 1道难题 = 2道中等题 = 6道简单题
7+
- 每日目标:做到需要收费的时候每天4题及其以下
8+
- 160题附近开始收费,此时已完成所有基础数据结构(除图外)
169

17-
- 数据结构和算法是核心
18-
- 排序算法需要全部能够实现
19-
- 需要会所有的图(线性表和二叉树都是特殊的图,字符串是特殊的线性表)
20-
- 需要能够手动实现一个 hash
10+
### 2. 编码规范
11+
- 变量定义域按照C语言使用(更加规范)
12+
- 算法实现需同时保证性能和可读性
13+
- 变量命名规则:
14+
- `des_XXX`: 表示目标值
15+
- `rec_f`: 表示递归/迭代函数
2116

22-
## 算法实现
17+
### 3. 算法实现标准
18+
- 时间复杂度:需要达到最低
19+
- 空间复杂度:不超过O(n)即可,非必要不降低到O(1)
2320

24-
- 循环
25-
- 递归
21+
## 二、核心知识体系
2622

27-
- 递归 == 循环 + 栈
28-
- (因为递归本来就是通过栈和循环实现的)
29-
- *`递归和循环的S、T一般相同`*
23+
### 1. 数据结构基础
24+
- 排序算法:需要全部掌握
25+
- 图论:包括线性表和二叉树(都是特殊的图)
26+
- 哈希:需要能够手动实现
3027

31-
## 算法使用的数据结构
28+
### 2. 算法实现方式
29+
- 循环实现
30+
- 递归实现
31+
- 重要概念:递归 == 循环 + 栈
32+
- *递归和循环的空间、时间复杂度一般相同*
33+
- 递归本质是通过栈和循环实现
3234

35+
### 3. 基础数据结构
3336
1. 线性表
34-
2. 字符串
37+
2. 字符串(特殊的线性表)
3538
3.
36-
1. 线段树(segment tree)/树状数组(Binary Indexed Tree,BIT)
39+
- 线段树(segment tree)
40+
- 树状数组(Binary Indexed Tree,BIT)
3741
4.
3842

39-
## 算法思想
43+
### 4. 核心算法思想
4044

41-
1. 贪心算法(最长递增子序列)
45+
#### 4.1 贪心算法
46+
- 典型应用:最长递增子序列
4247

43-
2. 动态规划
44-
- 一般动态规划
45-
- 记忆化动态规划
46-
- Memoization(375)/记忆化搜索(从后往前看的递归动态规划/本质是动态规划的逆向思维 & 递归)
48+
#### 4.2 动态规划
49+
- 一般动态规划
50+
- 记忆化动态规划
51+
- Memoization(375)
52+
- 记忆化搜索(从后往前看的递归动态规划)
53+
- 动态规划本质:
54+
- 数学归纳法(递推公式)
55+
- f(x) = f(x - 1) + f(x - 2) + ...
4756

48-
- 动态规划的本质:
49-
- 数学归纳法(递推公式)
50-
- f(x) = f(x - 1) + f(x - 2) + ...(第n项的结果由前面的某m项决定)
57+
#### 4.3 回溯算法(216)
58+
```python
59+
if condition_if:
60+
des_arr.append(path[:])
61+
else:
62+
for condition_for:
63+
path.append()
64+
traceback()
65+
path.pop()
66+
```
5167

52-
3. traceback(216)
68+
#### 4.4 分治算法
5369

54-
```
55-
if condition_if:
56-
des_arr.append(path[:])
57-
else:
58-
for condition_for:
59-
path.append()
60-
traceback()
61-
path.pop()
62-
```
63-
64-
4. divide-and-conquer algorithm
65-
66-
### 贪心算法难题
70+
## 三、难题分类总结
6771

72+
### 1. 贪心算法难题
6873
| 题号 | 时间复杂度 | 题目 | 完成方法 |
6974
|-----|------------|--------------------------------|---------------------|
7075
| 300 | O(nlog(n)) | Longest Increasing Subsequence | |
71-
| 162 | | | |
72-
| 179 | | | (内置排序算法,想到但是不能排序出来) |
76+
| 162 | | | 未证明可行性 |
77+
| 179 | | | 内置排序算法,想到但不能排序出来 |
7378
| 334 | O(n) | triplet | 两个数组最优置换 |
7479

75-
- 未证明可行性:
76-
162
77-
- 看答案做出题:
78-
- 179(内置排序算法,想到但是不能排序出来)
79-
```
80-
nums = [2, 1, 3, 4, 1, 2, 3, 4]
81-
def cmp(x, y):
82-
return x - y # -1 理解为 每次 x 取出最小的一个 x(java的比较函数就是这样)
83-
nums.sort(key=functools.cmp_to_key(cmp))
84-
print(nums) # [1, 1, 2, 2, 3, 3, 4, 4]
85-
```
86-
- 322(换零钱问题,在这里需要使用记忆化搜索实现)
87-
- 375(miniMax, 需要使用缓存方式来进行搜索)
88-
- 395(分治最长子字符串所有字符数量都不小于k)
89-
90-
### 回溯思想难题
91-
92-
题目序号:39 78 90
93-
94-
### 动态规划难题
80+
#### 特殊情况说明:
81+
- 179题排序示例:
82+
```python
83+
nums = [2, 1, 3, 4, 1, 2, 3, 4]
84+
def cmp(x, y):
85+
return x - y # -1 理解为每次x取出最小的一个x
86+
nums.sort(key=functools.cmp_to_key(cmp))
87+
print(nums) # [1, 1, 2, 2, 3, 3, 4, 4]
88+
```
9589

96-
题目序号:73,139,337(二叉树的动态规划), 392(使用动态规划来理解和做是难点)
90+
### 2. 回溯思想难题
91+
- 核心题目:39, 78, 90
9792

98-
### 时间上面需要提升的题目
93+
### 3. 动态规划难题
94+
- 关键题目:73, 139, 337(二叉树的动态规划), 392(使用动态规划理解是难点)
9995

96+
### 4. 需要优化的题目
10097
| 题目序号 | 题目描述 | 总结 |
10198
|------|-------------------------------------------------|----|
10299
| 105 | 需要加深二叉树 先序\|中序 遍历特性的理解 | ? |
103100
| 106 | 需要加深二叉树 中序\|后序 遍历特性的理解 | ? |
104101
| 130 | 广度优先遍历/二维数组 | ? |
105-
| 307 | 线段树(segment tree)/树状数组(Binary Indexed Tree,BIT) | ? |
102+
| 307 | 线段树/树状数组 | ? |
106103

107-
### 未做出来题目
108-
109-
| 题目序号 | 知识点 | 总数 |
104+
### 5. 未解决题目
105+
| 题目序号 | 知识点 | 序号 |
110106
|-------------------------------|-----------|----|
111-
| 95(3)96(3)[需要做出98题再来做这两题] | 树的遍历 | 1 |
107+
| 95(3)96(3)[需要做出98题再来做这两题] | 树的遍历 | 1 |
112108
| 241 |95 一个类型 | 2 |
113109
| 292 | NIM游戏和博弈论 | 3 |
114-
| 309(多个数组动态规划) | 股票买卖/要冷却 | 4 |
115-
| 310(图变树)[超时后看答案解出来的,类似找重心的过程] | 减节点/树的直径 | 5 |
116-
117-
### bit manipulation(位运算)
110+
| 309 | 股票买卖/要冷却 | 4 |
111+
| 310[超时后看答案解出来的,类似找重心的过程] | 减节点/树的直径 | 5 |
118112

119-
| 编号 | ... | ... | ... |
120-
|-----|-----|-----|-----|
121-
| 201 | ... | ... | ... |
113+
## 四、特殊专题
122114

123-
### 其他
124-
125-
#### 数学
115+
### 1. 位运算
116+
| 编号 | 知识点 |
117+
|-----|-----|
118+
| 201 | ... |
126119

120+
### 2. 数学专题
127121
| 题目序号 | 题目知识 |
128122
|------|-----------------------|
129123
| 204 | prime |
130124
| 279 | 四平方定理 |
131-
| 372 | [372 super pow](#372) |
132-
133-
- <span id="372">372 super pow</span>
134-
- 涉及知识 (x * y) % m == ((x % m)*(y % m)) % m
135-
- 该表达式可以分类讨论得以证明,具有递归累计效果
125+
| 372 | super pow |
136126

137-
#### 有趣的题目
127+
#### 372题重要知识点
128+
- (x * y) % m == ((x % m)*(y % m)) % m
129+
- 该表达式可以分类讨论证明,具有递归累计效果
138130

131+
### 3. 有趣的题目
139132
| 题目序号 | 描述 |
140133
|------|-------------------------------------------------------|
141134
| 205 | 同构字符串 |
@@ -148,12 +141,14 @@
148141
| 287 | Floyd 数组重复数字判定/抽屉原理 |
149142
| 292 | NIM游戏、博弈论 |
150143
| 319 | 灯泡开关(brainteaser) |
151-
| 380 | Insert Delete GetRandom O(1)[使用 hash 实现] |
152-
| 496 | Next Greater Element I[stack & expression evaluation] |
144+
| 380 | Insert Delete GetRandom O(1) |
145+
| 496 | Next Greater Element I |
153146

154-
#### 二进制知识点
147+
## 五、技巧总结
155148

156-
| 操作 | 意义 |
157-
|-----------|----------------|
158-
| x&(x - 1) | 用来去除 x 的最右边的 1 |
149+
### 二进制操作技巧
150+
| 操作 | 意义 |
151+
|-----------|----------------------|
152+
| x&(x - 1) | 用来去除 x 的最右边的 1 |
153+
| x&(-x) | lowbit,也就是取出最低位代表的数字 |
159154

python/.DS_Store

6 KB
Binary file not shown.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from collections import defaultdict
2+
from typing import List, Dict, Set
3+
4+
5+
class Solution:
6+
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
7+
"""
8+
计算除法表达式的结果
9+
10+
Args:
11+
equations: 表达式列表,每个表达式形如 ["a", "b"] 表示 a/b
12+
values: 对应表达式的值
13+
queries: 需要计算的查询列表
14+
15+
Returns:
16+
List[float]: 查询结果列表,如果无法计算则返回 -1.0
17+
18+
Time: O(Q * (V + E)) 其中 Q 是查询数量,V 是变量数量,E 是方程数量
19+
Space: O(V^2) 用于存储图的邻接表
20+
"""
21+
# 构建图的邻接表
22+
graph: Dict[str, Dict[str, float]] = defaultdict(dict)
23+
for (dividend, divisor), value in zip(equations, values):
24+
graph[dividend][divisor] = value
25+
graph[divisor][dividend] = 1.0 / value
26+
27+
def dfs(start: str, target: str, visited: Set[str]) -> float:
28+
"""深度优先搜索计算结果"""
29+
# 处理特殊情况
30+
if start not in graph or target not in graph:
31+
return -1.0
32+
if start == target:
33+
return 1.0
34+
if target in graph[start]:
35+
return graph[start][target]
36+
37+
visited.add(start)
38+
# 遍历所有可能的路径
39+
for next_node, value in graph[start].items():
40+
if next_node not in visited:
41+
result = dfs(next_node, target, visited)
42+
if result != -1.0:
43+
# 这个充分利用了题目的条件,我的之前的代码更具有普适性
44+
return value * result
45+
visited.remove(start)
46+
return -1.0
47+
48+
# 处理所有查询
49+
return [dfs(start, target, set()) for start, target in queries]
50+
51+
52+
def test_solution():
53+
"""测试用例"""
54+
test_cases = [
55+
(
56+
[["a", "b"], ["c", "d"]],
57+
[1.0, 1.0],
58+
[["a", "c"], ["b", "d"], ["b", "a"], ["d", "c"]],
59+
[-1.0, -1.0, 1.0, 1.0]
60+
),
61+
(
62+
[["a", "b"], ["b", "c"]],
63+
[2.0, 3.0],
64+
[["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"]],
65+
[6.0, 0.5, -1.0, 1.0, -1.0]
66+
)
67+
]
68+
69+
solution = Solution()
70+
for i, (equations, values, queries, expected) in enumerate(test_cases, 1):
71+
result = solution.calcEquation(equations, values, queries)
72+
assert result == expected, f"Test case {i} failed: expected {expected}, got {result}"
73+
print(f"Test case {i} passed!")
74+
75+
76+
if __name__ == '__main__':
77+
test_solution()

0 commit comments

Comments
 (0)