【代码随想录——回溯算法——四周目】

devtools/2024/10/16 0:18:52/

1.重新安排行程

在这里插入图片描述

1.1 我的代码,超时通不过

var (used   []boolpath   []stringres    []stringisFind bool
)func findItinerary(tickets [][]string) []string {sortTickets(tickets)res = make([]string, len(tickets)+1)path = make([]string, 0)used = make([]bool, len(tickets))isFind = falsestart := "JFK"path = append(path, start)dfs(start, 0, tickets)return res
}func dfs(start string, num int, tickets [][]string) {if isFind {return}if num == len(tickets) {copy(res, path)isFind = truereturn}for i := 0; i < len(tickets); i++ {// 当前机票未使用,且起点为startif !used[i] && tickets[i][0] == start {used[i] = truepath = append(path, tickets[i][1])dfs(tickets[i][1], num+1, tickets)if isFind {return}path = path[:len(path)-1]used[i] = false}}
}func sortTickets(tickets [][]string) {sort.Slice(tickets, func(i, j int) bool {if tickets[i][0] == tickets[j][0] {return tickets[i][1] < tickets[j][1]}return tickets[i][0] < tickets[j][0]})
}

1.2 正确的解法

首先先把图的邻接表存进字典,并且按字典序排序,然后从‘JFK’开始深搜,每前进一层就减去一条路径,直到某个起点不存在路径的时候就会跳出while循环进行回溯,相对先找不到路径的一定是放在相对后面,所以当前搜索的起点from会插在当前输出路径的第一个位置。

// No.332 重新安排行程
type pair struct {// pair储存机票目的地和当前航线是否已经使用target  stringvisited bool
}// 储存pair数组,实现sort接口
type pairs []*pairfunc (p pairs) Len() int {return len(p)
}func (p pairs) Swap(i, j int) {p[i], p[j] = p[j], p[i]
}func (p pairs) Less(i, j int) bool {return p[i].target < p[j].target
}func findItinerary(tickets [][]string) (res []string) {// record储存每个机场可到达的目的地,以及当前航线是否已选择targets := make(map[string]pairs, 0)for _, ticket := range tickets {if targets[ticket[0]] == nil {targets[ticket[0]] = make(pairs, 0)}// 添加新的可达目的地,初始置为未选择targets[ticket[0]] = append(targets[ticket[0]], &pair{target: ticket[1], visited: false})}for k := range targets {// 按字典升序排序目的地,保证第一个选出的就是字典序最小的结果sort.Sort(targets[k])}var backtrack func() boolbacktrack = func() bool {if len(tickets)+1 == len(res) {// 结果机场数量比票数大1说明已经构建出所有路径,找到了结果return true}// 当前所在机场here := res[len(res)-1]for i, t := range targets[here] {if i > 0 && targets[here][i-1].target == t.target && !targets[here][i-1].visited {// 剪枝(非常重要),如果上一个目的地和当前的相同,且上一个没用过,说明是从上一个回溯回来的// 上一个不可能那么当前的也不可能,直接跳过continue}// 枚举所有可能的目的地,已经使用过的航线除外if !t.visited {res = append(res, t.target)t.visited = trueif backtrack() {return true}res = res[:len(res)-1]t.visited = false}}return false}// 所有机票从JFK出发res = append(res, "JFK")backtrack()return
}

2.N皇后

在这里插入图片描述

var (res  [][]stringpath [][]int
)func solveNQueens(n int) [][]string {res = make([][]string, 0)path = make([][]int, n)for i := 0; i < n; i++ {path[i] = make([]int, n)}dfs(n, 0)return res
}func dfs(n int, curRow int) {if curRow == n {temp := make([]string, 0)for i := 0; i < n; i++ {str := ""for j := 0; j < n; j++ {if path[i][j] == 0 {str = str + "."} else {str = str + "Q"}}temp = append(temp, str)}res = append(res, temp)}for i := 0; i < n; i++ {if canPlaceQueen(curRow, i, n) {path[curRow][i] = 1dfs(n, curRow+1)path[curRow][i] = 0}}
}func canPlaceQueen(row, col, n int) bool {if row >= n || col >= n || row < 0 || col < 0 {return false}// 检查同行同列的情况for i := 0; i < n; i++ {if path[i][col] == 1 {return false}if path[row][i] == 1 {return false}}// 检查主对角线row1, col1 := row, colfor row1 >= 0 && col1 >= 0 {if path[row1][col1] == 1 {return false}row1--col1--}row1, col1 = row, colfor row1 < n && col1 < n {if path[row1][col1] == 1 {return false}row1++col1++}// 检查副对角线row1, col1 = row, colfor row1 >= 0 && col1 < n {if path[row1][col1] == 1 {return false}row1--col1++}row1, col1 = row, colfor row1 < n && col1 >= 0 {if path[row1][col1] == 1 {return false}row1++col1--}return true
}

3.解数独

在这里插入图片描述

var (chunks     [9][]boolrows       [9][]boolcols       [9][]boolmatrixSize int  = 9emptyCount int  = 0hasFind    bool = false
)func solveSudoku(board [][]byte) {emptyCount = 0hasFind = falsefor i := 0; i < matrixSize; i++ {chunks[i] = make([]bool, 10) //用来表示每个区域中的数字1-9是否已经被使用rows[i] = make([]bool, 10)   //用来表示每行中的数字1-9是否已经被使用cols[i] = make([]bool, 10)   //用来表示每列中的数字1-9是否已经被使用}for i := 0; i < matrixSize; i++ {for j := 0; j < matrixSize; j++ {if board[i][j] != '.' {num := board[i][j] - '0'chunkId := findChunkIndex(i, j)chunks[chunkId][num] = truerows[i][num] = truecols[j][num] = true} else {emptyCount++}}}dfs(emptyCount, board, &hasFind)
}func dfs(emptyCount int, board [][]byte, hasFind *bool) {if *hasFind { //在其他分支已经找到答案了return}if emptyCount == 0 { //空格全部填完,找到答案*hasFind = truereturn}for i := 0; i < matrixSize; i++ {for j := 0; j < matrixSize; j++ {if board[i][j] == '.' {for num := byte(1); num <= 9; num++ {if canPlaceNumber(i, j, num) {chunkId := findChunkIndex(i, j)board[i][j] = '0' + numchunks[chunkId][num] = truerows[i][num] = truecols[j][num] = trueemptyCount--dfs(emptyCount, board, hasFind)if *hasFind { //在其他分支已经找到答案了return}chunks[chunkId][num] = falserows[i][num] = falsecols[j][num] = falseboard[i][j] = '.'emptyCount++}}return}}}
}
//查看在该位置是否能放下该数
func canPlaceNumber(row, col int, num byte) bool {//行列中是否已经有这个数if rows[row][num] || cols[col][num] {return false}//3*3的块中是否有这个数if chunks[findChunkIndex(row, col)][num] {return false}return true
}
//找到所属的3*3的块
func findChunkIndex(row, col int) int {return (row/3)*3 + col/3
}

http://www.ppmy.cn/devtools/44916.html

相关文章

NAT简介

一、NAT 概念定义 NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;是一种将私有 IP 地址转换为公有 IP 地址的技术。 允许一个组织内部使用私有 IP 地址的网络通过少量的公有 IP 地址连接到互联网。实现了私有网络与外部网络的通信&#xf…

NBM 算法【python,算法,机器学习】

朴素贝叶斯法&#xff08;Naive Bayes model&#xff09;是基于贝叶斯定理与特征条件独立假设的分类方法。 贝叶斯定理 P ( A ∣ B ) P ( B ∣ A ) ∗ P ( A ) P ( B ) P(A|B)\frac{P(B|A) * P(A)}{P(B)} P(A∣B)P(B)P(B∣A)∗P(A)​ 其中A表示分类&#xff0c;B表示属性&…

【前端Vue】——课堂笔记(二)

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…

如何从异步调用中返回响应

想象一下,你打电话给朋友并让他帮你查一些资料。虽然这可能需要一段时间,但你会在电话里等待,直到朋友给你需要的答案。这就是同步调用的行为: function findItem() {var item;while (item_not_found) {// 查找}return item; }var item = findItem(); // 使用 item doSome…

JavaScript base64 与 File 之间的互转

JavaScript base64 与 File 之间的互转 一、base64 > File 在 JavaScript 中&#xff0c;可以使用 Blob 对象将 base64 字符串转换为 File 对象。 方法一、base64 直接转换为 File 对象&#xff1a; 首先, 需要从 base64 字符串中获取文件类型, 然后将文件类型和 base64…

react antd table表格如何获取当前行id

组件库上都有详细的介绍&#xff0c;有自带的一些属性&#xff01;

Redis 主从复制

前言 在分布式系统中为了解决单点问题&#xff0c;通常会把数据复制多个副本部署到其他服务器&#xff0c;满⾜故障恢复和负载均衡等需求。Redis 也是如此&#xff0c;它为我们提供了复制的功能&#xff0c;实现了相同数据的多个 Redis 副本。复制功能是⾼可⽤ Redis 的基础&am…

家政预约小程序10公众号集成

目录 1 使用测试号3 工作流配置4 配置关注事件脚本5 注册开放平台6 获取公众号access_token6 实现关注业务逻辑总结 我们本次实战项目构建的相当于一个预约平台&#xff0c;既有家政企业&#xff0c;也有家政服务人员还有用户。不同的人员需要收到不同的消息&#xff0c;比如用…