回溯法 深度优先 递归 回溯不一定借助递归
动态规划 游标
55. 跳跃游戏 - 力扣(LeetCode) https://leetcode.cn/problems/jump-game/
import "log" func max(a, b int) int { if a > b { return a } return b } // [1] [0] func canJump(nums []int) bool { n := len(nums) - 1 var rightMost int = nums[0] for i := 0; i <= n; i++ { log.Println(rightMost, " ", i) if i > rightMost { return false } rightMost = max(rightMost, i+nums[i]) if rightMost >= n { return true } } return false }
小结:
1、注意12题、13题问题的差异:12题要求路径的连贯性,中间路径不能中断,13题没有这样的要求。
https://leetcode-cn.com/problems/word-search/
https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
剑指 Offer 12. 矩阵中的路径
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true
示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd" 输出:false
提示:
1 <= board.length <= 200
1 <= board[i].length <= 200
board
和word
仅由大小写英文字母组成
注意:本题与主站 79 题相同:https://leetcode-cn.com/problems/word-search/
func dfs(i, j, k int, board [][]byte, word string, used [][]int) bool { n := len(word) if k == n { return true } r := len(board) c := len(board[0]) if i < 0 || i >= r || j < 0 || j >= c { return false } if used[i][j] == 1 { return false } if board[i][j] != word[k] { return false } used[i][j] = 1 b := dfs(i+1, j, k+1, board, word, used) || dfs(i-1, j, k+1, board, word, used) || dfs(i, j+1, k+1, board, word, used) || dfs(i, j-1, k+1, board, word, used) return b } /* [["A","B","C","E"],["S","F","E","S"],["A","D","E","E"]] "ABCESEEEFS" */ func exist(board [][]byte, word string) bool { n := len(word) r := len(board) c := len(board[0]) if n > r*c { return false } used := func() [][]int { l := [][]int{} for i := 0; i < r; i++ { ll := []int{} for ii := 0; ii < c; ii++ { ll = append(ll, 0) } l = append(l, ll) } return l } for i := 0; i < r; i++ { for j := 0; j < c; j++ { if dfs(i, j, 0, board, word, used()) { return true } } } return false }
在有多条路可以选择的时候,选错了无法回头。
提前使用了不该走的路。
func dfs(i, j, k int, board [][]byte, word string, used ...[]int) bool { n := len(word) if k == n { return true } r := len(board) c := len(board[0]) if i < 0 || i >= r || j < 0 || j >= c { return false } if board[i][j] != word[k] { return false } for _, v := range used { a, b := v[0], v[1] if a == i && b == j { return false } } if dfs(i+1, j, k+1, board, word, append(used, []int{i, j})...) { return true } if dfs(i-1, j, k+1, board, word, append(used, []int{i, j})...) { return true } if dfs(i, j+1, k+1, board, word, append(used, []int{i, j})...) { return true } if dfs(i, j-1, k+1, board, word, append(used, []int{i, j})...) { return true } return false } /* [["A","B","C","E"],["S","F","E","S"],["A","D","E","E"]] "ABCESEEEFS" */ func exist(board [][]byte, word string) bool { n := len(word) r := len(board) c := len(board[0]) if n > r*c { return false } for i := 0; i < r; i++ { for j := 0; j < c; j++ { if dfs(i, j, 0, board, word) { return true } } } return false }
回溯法 深度优先搜索 注意传参-走过的坐标
func exist(board [][]byte, word string) bool { n := len(word) r := len(board) c := len(board[0]) if n > r*c { return false } var dfs func(i, j, k int, used ...[]int) bool dfs = func(i, j, k int, used ...[]int) bool { n := len(word) if k == n { return true } r := len(board) c := len(board[0]) if i < 0 || i >= r || j < 0 || j >= c { return false } if board[i][j] != word[k] { return false } for _, v := range used { a, b := v[0], v[1] if a == i && b == j { return false } } if dfs(i+1, j, k+1, append(used, []int{i, j})...) { return true } if dfs(i-1, j, k+1, append(used, []int{i, j})...) { return true } if dfs(i, j+1, k+1, append(used, []int{i, j})...) { return true } if dfs(i, j-1, k+1, append(used, []int{i, j})...) { return true } return false } for i := 0; i < r; i++ { for j := 0; j < c; j++ { if dfs(i, j, 0) { return true } } } return false }
func movingCount(m int, n int, k int) int { f := func(i int) int { return i/10 + i%10 } used := [][]int{} var dfs func(i, j int) int dfs = func(i, j int) int { if i < 0 || i >= m || j < 0 || j >= n { return 0 } for _, v := range used { a, b := v[0], v[1] if a == i && b == j { return 0 } } ok := func() bool { c := 0 if i == 100 { c++ } if j == 100 { c++ } c += f(i) + f(j) return c <= k }() if !ok { return 0 } used = append(used, []int{i, j}) return 1 + dfs(i-1, j) + dfs(i+1, j) + dfs(i, j-1) + dfs(i, j+1) } c := 0 for i := 0; i < m; i++ { for j := 0; j < n; j++ { v := dfs(i, j) if c < v { c = v } } } return c }
https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/
地上有一个m行n列的方格,从坐标 [0,0]
到坐标 [m-1,n-1]
。一个机器人从坐标 [0, 0]
的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1 输出:3
示例 2:
输入:m = 3, n = 1, k = 0 输出:1
提示:
1 <= n,m <= 100
0 <= k <= 20