# 卿è§å
## èæ¯
å
ä»ä¸éé¢ç®å¼å§~
å¦é¢  [triangle](https://leetcode-cn.com/problems/triangle/)
> ç»å®ä¸ä¸ªä¸è§å½¢ï¼æ¾åºèªé¡¶åä¸çæå°è·¯å¾åãæ¯ä¸æ¥åªè½ç§»å¨å°ä¸ä¸è¡ä¸ç¸é»çç»ç¹ä¸ã
ä¾å¦ï¼ç»å®ä¸è§å½¢ï¼
```text
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
```
èªé¡¶åä¸çæå°è·¯å¾å为  11ï¼å³ï¼2 + 3 + 5 + 1 = 11ï¼ã
ä½¿ç¨ DFSï¼éå æè
åæ²»æ³ï¼
éå

åæ²»æ³

ä¼å DFSï¼ç¼åå·²ç»è¢«è®¡ç®çå¼ï¼ç§°ä¸ºï¼è®°å¿åæç´¢ æ¬è´¨ä¸ï¼å¨æè§åï¼

卿è§åå°±æ¯æå¤§é®é¢åæå°é®é¢ï¼å¹¶è§£å³äºå°é®é¢éå¤è®¡ç®çæ¹æ³ç§°ä¸ºå¨æè§å
卿è§åå DFS åºå«
- äºåæ åé®é¢æ¯æ²¡æäº¤éï¼æä»¥å¤§é¨åäºåæ é½ç¨é彿è
åæ²»æ³ï¼å³ DFSï¼å°±å¯ä»¥è§£å³
- å triangle è¿ç§æ¯æéå¤èµ°çæ
åµï¼**åé®é¢æ¯æäº¤é**ï¼æä»¥å¯ä»¥ç¨å¨æè§åæ¥è§£å³
卿è§åï¼èªåºåä¸
```go
func minimumTotal(triangle [][]int) int {
if len(triangle) == 0 || len(triangle[0]) == 0 {
return 0
}
// 1ãç¶æå®ä¹ï¼f[i][j] 表示ä»i,jåºåï¼å°è¾¾æåä¸å±çæçè·¯å¾
var l = len(triangle)
var f = make([][]int, l)
// 2ãåå§å
for i := 0; i < l; i++ {
for j := 0; j < len(triangle[i]); j++ {
if f[i] == nil {
f[i] = make([]int, len(triangle[i]))
}
f[i][j] = triangle[i][j]
}
}
// 3ã鿍æ±è§£
for i := len(triangle) - 2; i >= 0; i-- {
for j := 0; j < len(triangle[i]); j++ {
f[i][j] = min(f[i+1][j], f[i+1][j+1]) + triangle[i][j]
}
}
// 4ãçæ¡
return f[0][0]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
```
卿è§åï¼èªé¡¶åä¸
```go
// æµè¯ç¨ä¾ï¼
// [
// [2],
// [3,4],
// [6,5,7],
// [4,1,8,3]
// ]
func minimumTotal(triangle [][]int) int {
if len(triangle) == 0 || len(triangle[0]) == 0 {
return 0
}
// 1ãç¶æå®ä¹ï¼f[i][j] 表示ä»0,0åºåï¼å°è¾¾i,jçæçè·¯å¾
var l = len(triangle)
var f = make([][]int, l)
// 2ãåå§å
for i := 0; i < l; i++ {
for j := 0; j < len(triangle[i]); j++ {
if f[i] == nil {
f[i] = make([]int, len(triangle[i]))
}
f[i][j] = triangle[i][j]
}
}
// 鿍æ±è§£
for i := 1; i < l; i++ {
for j := 0; j < len(triangle[i]); j++ {
// è¿éåä¸ºä¸¤ç§æ
åµï¼
// 1ãä¸ä¸å±æ²¡æå·¦è¾¹å¼
// 2ãä¸ä¸å±æ²¡æå³è¾¹å¼
if j-1 < 0 {
f[i][j] = f[i-1][j] + triangle[i][j]
} else if j >= len(f[i-1]) {
f[i][j] = f[i-1][j-1] + triangle[i][j]
} else {
f[i][j] = min(f[i-1][j], f[i-1][j-1]) + triangle[i][j]
}
}
}
result := f[l-1][0]
for i := 1; i < len(f[l-1]); i++ {
result = min(result, f[l-1][i])
}
return result
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
```
## éå½åå¨è§å
³ç³»
é彿¯ä¸ç§ç¨åºçå®ç°æ¹å¼ï¼å½æ°çèªæè°ç¨
```go
Function(x) {
...
Funciton(x-1);
...
}
```
卿è§åï¼æ¯ä¸ç§è§£å³é® é¢çææ³ï¼å¤§è§æ¨¡é®é¢çç»æï¼æ¯ç±å°è§æ¨¡é® é¢çç»æè¿ç®å¾æ¥çã卿è§åå¯ç¨é彿¥å®ç°(Memorization Search)
## 使ç¨åºæ¯
满足两个æ¡ä»¶
- æ»¡è¶³ä»¥ä¸æ¡ä»¶ä¹ä¸
- æ±æå¤§/æå°å¼ï¼Maximum/Minimum ï¼
- æ±æ¯å¦å¯è¡ï¼Yes/No ï¼
- æ±å¯è¡ä¸ªæ°ï¼Count(\*) ï¼
- 满足ä¸è½æåºæè
交æ¢ï¼Can not sort / swap ï¼
å¦é¢ï¼[longest-consecutive-sequence](https://leetcode-cn.com/problems/longest-consecutive-sequence/) ä½ç½®å¯ä»¥äº¤æ¢ï¼æä»¥ä¸ç¨å¨æè§å
## åç¹è¦ç´
1. **ç¶æ State**
- çµæï¼åé åï¼åå¨å°è§æ¨¡é®é¢çç»æ
2. æ¹ç¨ Function
- ç¶æä¹é´çèç³»ï¼æä¹éè¿å°çç¶æï¼æ¥ç®å¤§çç¶æ
3. åå§å Intialization
- ææéçå°ç¶ææ¯ä»ä¹, èµ·ç¹
4. çæ¡ Answer
- æå¤§çé£ä¸ªç¶ææ¯ä»ä¹ï¼ç»ç¹
## 常è§åç§ç±»å
1. Matrix DP (10%)
1. Sequence (40%)
1. Two Sequences DP (40%)
1. Backpack (10%)
> 注æç¹
>
> - è´ªå¿ç®æ³å¤§å¤é¢ç®é èçæ¡ï¼æä»¥å¦æè½ç¨å¨æè§å就尽éç¨å¨è§ï¼ä¸ç¨è´ªå¿ç®æ³
## 1ãç©éµç±»åï¼10%ï¼
### [minimum-path-sum](https://leetcode-cn.com/problems/minimum-path-sum/)
> ç»å®ä¸ä¸ªå
å«éè´æ´æ°ç  *m* x *n*Â ç½æ ¼ï¼è¯·æ¾åºä¸æ¡ä»å·¦ä¸è§å°å³ä¸è§çè·¯å¾ï¼ä½¿å¾è·¯å¾ä¸çæ°åæ»å为æå°ã
æè·¯ï¼å¨æè§å
1ãstate: f[x][y]ä»èµ·ç¹èµ°å° x,y çæçè·¯å¾
2ãfunction: f[x][y] = min(f[x-1][y], f[x][y-1]) + A[x][y]
3ãintialize: f[0][0] = A[0][0]ãf[i][0] = sum(0,0 -> i,0)ã f[0][i] = sum(0,0 -> 0,i)
4ãanswer: f[n-1][m-1]
```go
func minPathSum(grid [][]int) int {
// æè·¯ï¼å¨æè§å
// f[i][j] 表示i,jå°0,0çåæå°
if len(grid) == 0 || len(grid[0]) == 0 {
return 0
}
// å¤ç¨åæ¥çç©éµå表
// åå§åï¼f[i][0]ãf[0][j]
for i := 1; i < len(grid); i++ {
grid[i][0] = grid[i][0] + grid[i-1][0]
}
for j := 1; j < len(grid[0]); j++ {
grid[0][j] = grid[0][j] + grid[0][j-1]
}
for i := 1; i < len(grid); i++ {
for j := 1; j < len(grid[i]); j++ {
grid[i][j] = min(grid[i][j-1], grid[i-1][j]) + grid[i][j]
}
}
return grid[len(grid)-1][len(grid[0])-1]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
```
### [unique-paths](https://leetcode-cn.com/problems/unique-paths/)
> ä¸ä¸ªæºå¨äººä½äºä¸ä¸ª m x n ç½æ ¼çå·¦ä¸è§ ï¼èµ·å§ç¹å¨ä¸å¾ä¸æ 记为âStartâ ï¼ã
> æºå¨äººæ¯æ¬¡åªè½å䏿è
åå³ç§»å¨ä¸æ¥ãæºå¨äººè¯å¾è¾¾å°ç½æ ¼çå³ä¸è§ï¼å¨ä¸å¾ä¸æ 记为âFinishâï¼ã
> 鮿»å
±æå¤å°æ¡ä¸åçè·¯å¾ï¼
```go
func uniquePaths(m int, n int) int {
// f[i][j] 表示i,jå°0,0è·¯å¾æ°
f := make([][]int, m)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if f[i] == nil {
f[i] = make([]int, n)
}
f[i][j] = 1
}
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
f[i][j] = f[i-1][j] + f[i][j-1]
}
}
return f[m-1][n-1]
}
```
### [unique-paths-ii](https://leetcode-cn.com/problems/unique-paths-ii/)
> ä¸ä¸ªæºå¨äººä½äºä¸ä¸ª m x n ç½æ ¼çå·¦ä¸è§ ï¼èµ·å§ç¹å¨ä¸å¾ä¸æ 记为âStartâ ï¼ã
> æºå¨äººæ¯æ¬¡åªè½å䏿è
åå³ç§»å¨ä¸æ¥ãæºå¨äººè¯å¾è¾¾å°ç½æ ¼çå³ä¸è§ï¼å¨ä¸å¾ä¸æ 记为âFinishâï¼ã
> 鮿»å
±æå¤å°æ¡ä¸åçè·¯å¾ï¼
> ç°å¨èèç½æ ¼ä¸æéç¢ç©ãé£ä¹ä»å·¦ä¸è§å°å³ä¸è§å°ä¼æå¤å°æ¡ä¸åçè·¯å¾ï¼
```go
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
// f[i][j] = f[i-1][j] + f[i][j-1] å¹¶æ£æ¥éç¢ç©
if obstacleGrid[0][0] == 1 {
return 0
}
m := len(obstacleGrid)
n := len(obstacleGrid[0])
f := make([][]int, m)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if f[i] == nil {
f[i] = make([]int, n)
}
f[i][j] = 1
}
}
for i := 1; i < m; i++ {
if obstacleGrid[i][0] == 1 || f[i-1][0] == 0 {
f[i][0] = 0
}
}
for j := 1; j < n; j++ {
if obstacleGrid[0][j] == 1 || f[0][j-1] == 0 {
f[0][j] = 0
}
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
if obstacleGrid[i][j] == 1 {
f[i][j] = 0
} else {
f[i][j] = f[i-1][j] + f[i][j-1]
}
}
}
return f[m-1][n-1]
}
```
## 2ãåºåç±»åï¼40%ï¼
### [climbing-stairs](https://leetcode-cn.com/problems/climbing-stairs/)
> åè®¾ä½ æ£å¨ç¬æ¥¼æ¢¯ãéè¦ Â *n* é¶ä½ æè½å°è¾¾æ¥¼é¡¶ã
```go
func climbStairs(n int) int {
// f[i] = f[i-1] + f[i-2]
if n == 1 || n == 0 {
return n
}
f := make([]int, n+1)
f[1] = 1
f[2] = 2
for i := 3; i <= n; i++ {
f[i] = f[i-1] + f[i-2]
}
return f[n]
}
```
### [jump-game](https://leetcode-cn.com/problems/jump-game/)
> ç»å®ä¸ä¸ªéè´æ´æ°æ°ç»ï¼ä½ æåä½äºæ°ç»ç第ä¸ä¸ªä½ç½®ã
> æ°ç»ä¸çæ¯ä¸ªå
ç´ ä»£è¡¨ä½ å¨è¯¥ä½ç½®å¯ä»¥è·³è·çæå¤§é¿åº¦ã
> å¤æä½ æ¯å¦è½å¤å°è¾¾æåä¸ä¸ªä½ç½®ã
```go
func canJump(nums []int) bool {
// æè·¯ï¼çæåä¸è·³
// ç¶æï¼f[i] 表示æ¯å¦è½ä»0è·³å°i
// æ¨å¯¼ï¼f[i] = OR(f[j],j= i {
f[i] = true
}
}
}
return f[len(nums)-1]
}
```
### [jump-game-ii](https://leetcode-cn.com/problems/jump-game-ii/)
> ç»å®ä¸ä¸ªéè´æ´æ°æ°ç»ï¼ä½ æåä½äºæ°ç»ç第ä¸ä¸ªä½ç½®ã
> æ°ç»ä¸çæ¯ä¸ªå
ç´ ä»£è¡¨ä½ å¨è¯¥ä½ç½®å¯ä»¥è·³è·çæå¤§é¿åº¦ã
> ä½ çç®æ æ¯ä½¿ç¨æå°çè·³è·æ¬¡æ°å°è¾¾æ°ç»çæåä¸ä¸ªä½ç½®ã
```go
func jump(nums []int) int {
// ç¶æï¼f[i] 表示ä»èµ·ç¹å°å½åä½ç½®æå°æ¬¡æ°
// æ¨å¯¼ï¼f[i] = f[j],a[j]+j >=i,min(f[j]+1)
// åå§åï¼f[0] = 0
// ç»æï¼f[n-1]
f := make([]int, len(nums))
f[0] = 0
for i := 1; i < len(nums); i++ {
// f[i] æå¤§å¼ä¸ºi
f[i] = i
// éåä¹åç»æåä¸ä¸ªæå°å¼+1
for j := 0; j < i; j++ {
if nums[j]+j >= i {
f[i] = min(f[j]+1,f[i])
}
}
}
return f[len(nums)-1]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
```
### [palindrome-partitioning-ii](https://leetcode-cn.com/problems/palindrome-partitioning-ii/)
> ç»å®ä¸ä¸ªå符串 _s_ï¼å° _s_ å岿ä¸äºå串ï¼ä½¿æ¯ä¸ªå䏲齿¯åæä¸²ã
> è¿å符åè¦æ±çæå°å岿¬¡æ°ã
```go
func minCut(s string) int {
// state: f[i] "åi"个åç¬¦ç»æçåå符串éè¦æå°å 次cut(个æ°-1为索å¼)
// function: f[i] = MIN{f[j]+1}, j < i && [j+1 ~ i]è¿ä¸æ®µæ¯ä¸ä¸ªåæä¸²
// intialize: f[i] = i - 1 (f[0] = -1)
// answer: f[s.length()]
if len(s) == 0 || len(s) == 1 {
return 0
}
f := make([]int, len(s)+1)
f[0] = -1
f[1] = 0
for i := 1; i <= len(s); i++ {
f[i] = i - 1
for j := 0; j < i; j++ {
if isPalindrome(s, j, i-1) {
f[i] = min(f[i], f[j]+1)
}
}
}
return f[len(s)]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
func isPalindrome(s string, i, j int) bool {
for i < j {
if s[i] != s[j] {
return false
}
i++
j--
}
return true
}
```
注æç¹
- 夿åæå符串æ¶ï¼å¯ä»¥æåç¨å¨æè§åç®å¥½ï¼åå°æ¶é´å¤æåº¦
### [longest-increasing-subsequence](https://leetcode-cn.com/problems/longest-increasing-subsequence/)
> ç»å®ä¸ä¸ªæ åºçæ´æ°æ°ç»ï¼æ¾å°å
¶ä¸æé¿ä¸åååºåçé¿åº¦ã
```go
func lengthOfLIS(nums []int) int {
// f[i] 表示ä»0å¼å§å°iç»å°¾çæé¿åºåé¿åº¦
// f[i] = max(f[j])+1 ,a[j] b {
return a
}
return b
}
```
### [word-break](https://leetcode-cn.com/problems/word-break/)
> ç»å®ä¸ä¸ª**é空**å符串  *s* åä¸ä¸ªå
å«**é空**åè¯å表çåå
¸  *wordDict*ï¼å¤å®  *s* æ¯å¦å¯ä»¥è¢«ç©ºæ ¼æå为ä¸ä¸ªæå¤ä¸ªå¨åå
¸ä¸åºç°çåè¯ã
```go
func wordBreak(s string, wordDict []string) bool {
// f[i] 表示åi个å符æ¯å¦å¯ä»¥è¢«åå
// f[i] = f[j] && s[j+1~i] in wordDict
// f[0] = true
// return f[len]
if len(s) == 0 {
return true
}
f := make([]bool, len(s)+1)
f[0] = true
max := maxLen(wordDict)
for i := 1; i <= len(s); i++ {
for j := i - max; j < i && j >= 0; j++ {
if f[j] && inDict(s[j:i]) {
f[i] = true
break
}
}
}
return f[len(s)]
}
var dict = make(map[string]bool)
func maxLen(wordDict []string) int {
max := 0
for _, v := range wordDict {
dict[v] = true
if len(v) > max {
max = len(v)
}
}
return max
}
func inDict(s string) bool {
_, ok := dict[s]
return ok
}
```
å°ç»
常è§å¤çæ¹å¼æ¯ç» 0 ä½ç½®å ä½ï¼è¿æ ·å¤çé®é¢æ¶ä¸è§åä»ï¼åå§ååå¨åæ¥åºç¡ä¸ length+1ï¼è¿åç»æ f[n]
- ç¶æå¯ä»¥ä¸ºå i 个
- åå§å length+1
- åå¼ index=i-1
- è¿åå¼ï¼f[n]æè
f[m][n]
## Two Sequences DPï¼40%ï¼
### [longest-common-subsequence](https://leetcode-cn.com/problems/longest-common-subsequence/)
> ç»å®ä¸¤ä¸ªå符串  text1 å  text2ï¼è¿åè¿ä¸¤ä¸ªå符串çæé¿å
Œ
±ååºåã
> ä¸ä¸ªå符串ç  ååºå Â æ¯æè¿æ ·ä¸ä¸ªæ°çå符串ï¼å®æ¯ç±åå符串å¨ä¸æ¹åå符çç¸å¯¹é¡ºåºçæ
åµä¸å 餿äºå符ï¼ä¹å¯ä»¥ä¸å é¤ä»»ä½å符ï¼åç»æçæ°å符串ã
> ä¾å¦ï¼"ace" æ¯ "abcde" çååºåï¼ä½ "aec" 䏿¯ "abcde" çååºåã两个å符串çãå
Œ
±ååºåãæ¯è¿ä¸¤ä¸ªå符串æå
±åæ¥æçååºåã
```go
func longestCommonSubsequence(a string, b string) int {
// dp[i][j] aåi个åbåj个å符æé¿å
Œ
±ååºå
// dp[m+1][n+1]
// ' a d c e
// ' 0 0 0 0 0
// a 0 1 1 1 1
// c 0 1 1 2 1
//
dp:=make([][]int,len(a)+1)
for i:=0;i<=len(a);i++ {
dp[i]=make([]int,len(b)+1)
}
for i:=1;i<=len(a);i++ {
for j:=1;j<=len(b);j++ {
// ç¸çåå·¦ä¸å
ç´ +1ï¼å¦ååå·¦æä¸çè¾å¤§å¼
if a[i-1]==b[j-1] {
dp[i][j]=dp[i-1][j-1]+1
} else {
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
}
}
}
return dp[len(a)][len(b)]
}
func max(a,b int)int {
if a>b{
return a
}
return b
}
```
注æç¹
- go åçåå§å
```go
dp:=make([][]int,len(a)+1)
for i:=0;i<=len(a);i++ {
dp[i]=make([]int,len(b)+1)
}
```
- ä» 1 å¼å§éå尿大é¿åº¦
- ç´¢å¼éè¦åä¸
### [edit-distance](https://leetcode-cn.com/problems/edit-distance/)
> ç»ä½ 两个åè¯ Â word1 å  word2ï¼è¯·ä½ 计ç®åºå°  word1Â è½¬æ¢æ  word2 æä½¿ç¨çæå°æä½æ° Â
> ä½ å¯ä»¥å¯¹ä¸ä¸ªåè¯è¿è¡å¦ä¸ä¸ç§æä½ï¼
> æå
¥ä¸ä¸ªå符
> å é¤ä¸ä¸ªå符
> æ¿æ¢ä¸ä¸ªå符
æè·¯ï¼åä¸é¢å¾ç±»ä¼¼ï¼ç¸çåä¸éè¦æä½ï¼å¦ååå é¤ãæå
¥ãæ¿æ¢æå°æä½æ¬¡æ°çå¼+1
```go
func minDistance(word1 string, word2 string) int {
// dp[i][j] 表示aå符串çåi个å符ç¼è¾ä¸ºbå符串çåj个å符æå°éè¦å¤å°æ¬¡æä½
// dp[i][j] = OR(dp[i-1][j-1]ï¼a[i]==b[j],min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1)
dp:=make([][]int,len(word1)+1)
for i:=0;i