回溯法 深度优先 递归 回溯不一定借助递归

动态规划  游标 

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/

 

给定一个 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
 
 
 
 
 
 
 
 

 

posted @ 2022-04-24 01:31  papering  阅读(34)  评论(0编辑  收藏  举报