代码随想录 - Day35 - 回溯:重新安排行程,棋盘问题

2023-11-16

代码随想录 - Day35 - 回溯:重新安排行程,棋盘问题

332. 重新安排行程

输入:tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出:["JFK","ATL","JFK","SFO","ATL","SFO"]
解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。
只能取JFK开头的
取[JFK,SFO]
只能取JFK开头的
取[JFK,ATL]
只能取SFO开头的
取[SFO,ATL]
只能取ATL开头的
取[ATL,JFK]
只能取ATL开头的
取[ATL,SFO]
只能取ATL开头的
取[ATL,JFK]
只能取ATL开头的
取[ATL,SFO]
只能取JFK开头的
取[JFK,SFO]
只能取SFO开头的
取[SFO,ATL]
只能取JFK开头的
取[JFK,ATL]
没有可用的SFO开头的
只能取SFO开头的
取[SFO,ATL]
只能取ATL开头的
取[ATL,JFK]
只能取ATL开头的
取[ATL,SFO]
只能取ATL开头的
取[ATL,SFO]
只能取JFK开头的
取[JFK,SFO]
按字典序排列
[JFK,ATL,JFK,SFO,ATL,SFO] < [JFK,ATL,SFO,ATL,JFK,SFO] < [JFK,SFO,ATL,JFK,ATL,SFO]
取SFO加在后面
[JFK,ATL,JFK,SFO,ATL,SFO]
结束
[JFK,SFO], [JFK,ATL], [SFO,ATL], [ATL,JFK], [ATL,SFO]
[JFK,SFO]
[JFK,ATL]
取ATL加在后面
[JFK,SFO,ATL]
取JFK加在后面
[JFK,ATL,JFK]
取SFO加在后面
[JFK,ATL,SFO]
取JFK加在后面
[JFK,SFO,ATL,JFK]
取SFO加在后面
[JFK,SFO,ATL,SFO]
取SFO加在后面
[JFK,SFO,JFK,SFO]
取ATL加在后面
[JFK,ATL,SFO,ATL]
取ATL加在后面
[JFK,SFO,ATL,JFK,ATL]
取ATL加在后面
[JFK,ATL,JFK,SFO,ATL]
取JFK加在后面
[JFK,ATL,SFO,ATL,JFK]
取SFO加在后面
即[JFK,SFO,ATL,JFK,ATL,SFO]
取SFO加在后面
[JFK,ATL,SFO,ATL,JFK,SFO]
[JFK,ATL,JFK,SFO,ATL,SFO]最小

最终答案:行程有效 + 按字典排序最小
行程有效:

  • 第一个必须从JFK出发
  • 所有机票必须且只能用一次
class Solution:
    def backtracking(self, tickets, used, path, cur, result):
        if len(path) == len(tickets) + 1:   # 有效行程比票数大1,所以判断条件应该写成这样
            result.append(path[:])
            return True

        for i, ticket in enumerate(tickets):
            if ticket[0] == cur and used[i] == False:   # 没用过的机票 + 出发机场和上一次的到达机场必须是同一个
                used[i] = True  # 用过的机票设为True
                path.append(ticket[1])  # 只向path中添加到达机场
                state = self.backtracking(tickets, used, path, ticket[1], result)
                path.pop()  # 回溯,pop
                used[i] = False # 回溯,把机票设回False
                if state:   # 只要找到一个可行路径就返回,不继续搜索
                    return True

    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        result = []
        tickets.sort()  # 提前给tickets排序,这样收集到result时的顺序一定是字典序由小到大的
        path = ["JFK"]  # 第一个从JFK出发
        used = [False] * len(tickets)   # 没用过的tickets设为False
        self.backtracking(tickets, used, path, "JFK", result)
        return result[0]

上述代码也可以写成这样:

class Solution:
    def backtracking(self, tickets, used, path, cur, result):
        if len(path) == len(tickets) + 1:
            result.append(path[:])
            return True

        for i in range(len(tickets)):
            if tickets[i][0] == cur and used[i] == False:
                used[i] = True
                path.append(tickets[i][1])
                state = self.backtracking(tickets, used, path, tickets[i][1], result)
                path.pop()
                used[i] = False
                if state:
                    return True

    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        result = []
        tickets.sort()
        path = ["JFK"]
        used = [False] * len(tickets)
        self.backtracking(tickets, used, path, "JFK", result)
        return result[0]

使用字典:比上面的代码复杂了一点,但是速度更快

defaultdict()中只能存在不同的 key。

  • 添加元素时([key1, value2]),如果defaultdict()里面已经有一个 key1 了({key1: value1}) ,就不会新建一个 key1,而是把 value2 添加在 key1 原本的 value1 后面({key1: [value1, value2]}
from collections import defaultdict

class Solution:
    def backtracking(self, targets, path, ticketNum):
        if len(path) == ticketNum + 1:
            return True  # 找到有效行程

        airport = path[-1]  # 当前机场(path中最后一个元素)
        destinations = targets[airport]  # 取机场字典中的当前机场对应的 value 值,即为当前机场可以到达的机场列表
        for i, dest in enumerate(destinations):
            targets[airport].pop(i)  # 标记已使用的机票(把第 i 张机票删掉)
            # pop掉的i对应的到达机场 == path.append()的dest表示的到达机场
            path.append(dest)  # 添加目的地到路径
            if self.backtracking(targets, path, ticketNum):
                return True  # 找到有效行程
            targets[airport].insert(i, dest)  # 回溯,恢复机票(把第 i 张机票插入回 i 的位置
            path.pop()  # 移除目的地
        return False  # 没有找到有效行程

    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        targets = defaultdict(list)  # 构建机场字典
        # 把出发机场作为 key,到达机场作为 value
        # 如 JFK : SFO, ATL
        for ticket in tickets:
            targets[ticket[0]].append(ticket[1])
        # 对到达机场列表进行排序
        # 如 JFK : SFO, ATL 排序为 JFK : ATL, SFO
        for airport in targets:
            targets[airport].sort()  

        path = ["JFK"]  # 起始机场为"JFK"
        self.backtracking(targets, path, len(tickets))
        return path   

这道题是困难题,但是,把图画出来之后觉得不是很难,思路也比较好想,就是代码不好写。
敲代码能力有很大的进步空间。
可能是因为敲的太少手生吧。

51. N皇后

n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击,即这 n 个皇后不能处于同一行 / 同一列 / 同一斜线。

给一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表皇后和空位。

不会,直接看题解。
画了个图辅助理解。
在这里插入图片描述

假设Q占据的格子为 [x, y] ,那么 [x1~xn, y][x, y1~yn][x+i, y+i][x-i, y-i],都不能再放其它Q了。要注意边界范围,所有的坐标都小于n

class Solution:
    def isValid(self, row, col, chessBoard):
        # 检查列
        for i in range(row):
            if chessBoard[i][col] == "Q":
                return False
        # 检查 45 度角是否有皇后
        i, j = row - 1, col - 1
        while i >= 0 and j >= 0:
            if chessBoard[i][j] == "Q":
                return False    # 左上方向已经存在皇后,不合法
            i -= 1
            j -= 1
        # 检查 135 度角是否有皇后
        i, j = row - 1, col + 1
        while i >= 0 and j < len(chessBoard):
            if chessBoard[i][j] == "Q":
                return False    # 右上方向已经存在皇后,不合法
            i -= 1
            j += 1

        return True

    def backtracking(self, n, row, chessBoard, result):
        if row == n:
            result.append(chessBoard[:])    # 棋盘填满,将当前解加入结果集
            return
        for col in range(n):
            if self.isValid(row, col, chessBoard):
                chessBoard[row] = chessBoard[row][:col] + 'Q' + chessBoard[row][col+1:]  # 放置皇后
                self.backtracking(n, row + 1, chessBoard, result)   # 递归到下一行
                chessBoard[row] = chessBoard[row][:col] + '.' + chessBoard[row][col+1:]  # 回溯,撤销当前位置的皇后


    def solveNQueens(self, n: int) -> List[List[str]]:
        result = []
        chessBoard = ['.' * n for _ in range(n)]  # 初始化棋盘
        self.backtracking(n, 0, chessBoard, result)
        return [[''.join(row) for row in solution] for solution in result]  # 变成字符串放进 list 返回

我想不通,明明我的思路没错,为什么代码总是报错!
找到问题了,因为字符串不能直接修改,所以只好用切片的方式修改,这样才能正常运行,并得到正确结果。

37. 解数独

这道题不让return,只能在原有board里修改
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
数独部分空格内已填入了数字,空白格用 '.' 表示。
数独只有一个解
借用代码随想录里面的图:
在这里插入图片描述

本题中棋盘的每一个位置都要放一个数字(而N皇后是一行只放一个皇后),并检查数字是否合法,解数独的树形结构要比N皇后更宽更深。
本题递归不用终止条件,解数独是要遍历整个树形结构寻找可能的叶子节点就立刻返回。
不用终止条件不会死循环
递归的下一层的棋盘一定比上一层的棋盘多一个数,等数填满了棋盘自然就终止(填满当然好了,说明找到结果了),所以不需要终止条件!
递归逻辑:
一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!

class Solution:
    def isValid(self, row, col, val, board):
        for i in range(9):
            if board[row][i] == str(val):
                return False
        for j in range(9):
            if board[j][col] == str(val):
                return False
        startRow = (row // 3) * 3
        startCol = (col // 3) * 3
        for i in range(startRow, startRow + 3):
            for j in range(startCol, startCol + 3):
                if board[i][j] == str(val):
                    return False
        return True

    def backtracking(self, board):
        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] != ".":
                    continue
                for k in range(1, 10):
                    k = str(k)
                    if self.isValid(i, j, k, board):
                        board[i][j] = k
                        if self.backtracking(board):
                            return True
                        board[i][j] = '.'
                return False
        return True

    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        self.backtracking(board)

今天这三道题让我感到恶心
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

代码随想录 - Day35 - 回溯:重新安排行程,棋盘问题 的相关文章

  • 如何关闭python服务器

    使用此代码来运行 python 服务器 import os from http server import SimpleHTTPRequestHandler HTTPServer os chdir c users owner desktop
  • Python - 定义常量列表或字典的最佳/最简洁的方法

    第一次使用堆栈溢出 我很高兴来到这里 简介 我最近开始了 Python 编程世界的神奇冒险 我喜欢它 现在 在我从 C 语言的尴尬过渡中 一切都进展顺利 但我在创建与标头文件 h 同义的内容时遇到了麻烦 问题 我有中等大小的字典和列表 大约
  • pandas python 根据一个或多个其他列的子集更新 A 列的子集

    Edit我修改了下面的部分描述 以澄清 功能 和 组 的含义 修复拼写错误 并包含我尝试过的其他代码 我的熊猫df有 450 万行和 23 列 下表显示了几行df2这是从生成的df 它显示了两组 eeskin and hduquant 和三
  • 如何在 python 中使用 libSVM 计算精度、召回率和 F 分数

    我想计算precision recall and f score using libsvm在Python中 但我不知道如何 我已经发现这个网站 http www csie ntu edu tw cjlin libsvmtools eval
  • 为什么具有复杂无穷大的 NumPy 运算会导致有趣的结果?

    我注意到复杂的无穷大的有趣结果 In 1 import numpy as np In 2 np isinf 1j np inf Out 2 True In 3 np isinf 1 1j np inf Out 3 True In 4 np
  • 代码 zip( *sorted( zip(units, error) ) ) 的作用是什么?

    对于我的申请units and errors始终是数值列表 我尝试用谷歌搜索每个部分的作用 并找出了 zip 的第一部分 它似乎 ziped list zip units errors 只需将单位和误差配对即可生成一个列表 如下所示 uni
  • Python 3.4.3 subprocess.Popen 在没有管道的情况下获取命令的输出?

    我试图将命令的输出分配给变量 而不让命令认为它正在通过管道传输 原因是 如果正在通过管道传输 则相关命令会给出未格式化的文本作为输出 但如果从终端运行 则会给出颜色格式化的文本 我需要获取这种颜色格式的文本 到目前为止我已经尝试了一些事情
  • Django REST Framework:无法使用视图名称解析超链接关系的 URL

    我已经广泛研究了这个相当常见的问题 但没有一个修复对我有用 我正在 REST 框架中构建 Django 项目 并希望使用超链接关系 用户可以拥有许多独立的汽车和路线 路线是位置的集合 这些是我的序列化器 class CarSerialize
  • 不使用 graphviz/web 可视化决策树

    由于某些限制 我无法使用 graphviz webgraphviz com 可视化决策树 工作网络与另一个世界是封闭的 问题 是否有一些替代实用程序或一些 Python 代码用于至少非常简单的可视化可能只是决策树的 ASCII 可视化 py
  • 如何在 sqlalchemy 中创建基于文字的查询?

    我创建了一个函数来创建表达式 def test operator1 operation operator2 return literal column operator1 op operation operator2 现在当我用 test
  • 在 PyCharm 中运行命令行命令

    你好 我正在使用Python 但之前从未真正使用过它 我收到一些命令 需要在终端中运行 基本上 python Test py GET feeds 我正在使用 PyCharm 我想知道是否有办法从该 IDE 中运行这些相同的命令 按 Alt
  • 如何使用lxml和python更新xml文件?

  • 使用主宰器将实时数据发送给客户端

    我尝试使用 Flask 的主宰框架 以便按照 Flask 代码片段将实时信息发送到客户端浏览器http flask pocoo org snippets 80 http flask pocoo org snippets 80 当我尝试为我的
  • 如何对嵌套函数进行单元测试? [复制]

    这个问题在这里已经有答案了 您将如何对嵌套函数进行单元测试f1 在下面的例子中 def f def f1 return 1 return 2 或者需要测试的函数不应该嵌套吗 有一个类似的问题这个链接 https stackoverflow
  • 将多个 isinstance 检查转换为结构模式匹配

    我想转换此现有代码以使用模式匹配 if isinstance x int pass elif isinstance x str x int x elif isinstance x float Decimal x round x else r
  • 如何使用JQuery和Django(ajax + HttpResponse)?

    假设我有一个 AJAX 函数 function callpage ajax method get url abc data x 3 beforeSend function success function html IF HTTPRESPO
  • python 中的异步编程

    python 中有异步编程的通用概念吗 我可以为一个函数分配一个回调 执行它并立即返回主程序流 无论该函数的执行需要多长时间吗 您所描述的 主程序流程在另一个函数执行时立即恢复 不是通常所说的 异步 又名 事件驱动 编程 而是 多任务 又名
  • 使用 Tweepy 获取推文时出错

    我有一个用于获取推文的 Python 脚本 在脚本中我使用该库 Tweepy 我使用有效的身份验证参数 运行此脚本后 一些推文存储在我的 MongoDB 中 有些则被 if 语句拒绝 但我仍然收到错误 requests packages u
  • Scrapy - 持续从数据库中获取要爬取的url

    我想不断地从数据库中获取要爬行的网址 到目前为止 我成功地从基地获取了 url 但我希望我的蜘蛛继续从该基地读取 因为该表将由另一个线程填充 我有一个管道 一旦爬行 工作 就会从表中删除 url 换句话说 我想使用我的数据库作为队列 我尝试
  • Pymongo 批量插入

    我正在尝试批量插入文档 但批量插入时不会插入超过 84 个文档 给我这个错误 in insert pymongo errors InvalidOperation cannot do an empty bulk insert 是否可以批量插入

随机推荐

  • 镜像下载boot.iso和dvd1.iso的区别;dnf:找不到命令;yum和dnf的区别;CentOS Stream和Linux的区别;dnf: command not found

    这里写目录标题 一 linux 的各个系列 二 End dates are coming in 2024 for CentOS Stream 8 and CentOS Linux 7 三 镜像下载boot iso和dvd1 iso的区别 四
  • [USB 3.0 报错]-高手必看!BIOS 设置中的 xHCI 模式以及 USB 2.0/3.0 的万能 Windows 驱动

    目录 关于 USB 3 0 报错符合 USB xHCI 的主机控制器 错误代码为 10 一个匪夷所思的 USB 3 0 问题 这种情况会导致哪些症状呢 破案了 这个困扰我大半年的问题其实是 intel xHCI 模式的设置问题 初识 xHC
  • 跳转控制语句

    跳转控制语句 continue 用在循环中 基于条件控制 跳过某次循环体内容的执行 继续下一次的执行 break 用在循环中 基于条件控制 终止循环体内容的执行 也就是说结束当前的整个循环 实例 public class ControlDe
  • 新手怎么做期货?一文让你找到方向

    改革开放40年以来 我国经济水平发展逐年上升 人均收入逐年增长 金融衍生品交易市场也随之逐渐繁荣 越来越多的投资者开始走进期货投资市场 其中不乏有新手不知道怎么炒期货 第一 首先要做的功课是了解自己的个性 做期货不是光靠技术 如果成功按10
  • 使用nps内网穿透的问题记录

    实现目标 将局部网 可访问互联网 设备的端口映射到公网服务器上 1 资料准备 下载nps server 和npc client 安装包 https github com ehang io nps releases 文档 https ehan
  • SpringCloud-消息驱动

    消息驱动 Spring Cloud Stream 概述 常见MQ 消息中间件 ActiveMQ RabbitMQ RocketMQ Kafka 有没有一种新的技术诞生 让我们不再关注具体MQ的细节 我们只需要用一种适配绑定的方式 自动的给我
  • 高并发模拟~多个线程同时发起请求

    高并发模拟 多个线程同时发起请求 两种方案 CyclicBarrier 栅栏 所有的线程必须同时到达栅栏位置 才能继续执行 CountDownLatch 计数器 一个线程或多个线程一直等待 直到其他线程执行的操作完成 1 CyclicBar
  • 【Mo&AI TIME 人工智能技术博客】矛与盾的对决——神经网络后门攻防

    本篇文章内容转载于 AI TIME论道 公众号 秉持着合作共享的信念 希望给热爱人工智能的你们 提供更全面 前沿的人工智能和学科发展资讯 2022年7月9日 AI TIME组织了Ph D Debate第十一期 题为 矛与盾的对决 神经网络后
  • Spring framework testing文档读书笔记

    该文章是我读Spring testing英文官方文档的读书笔记 方便以后快速的回忆文档里讲述的内容 而不用再去读一遍官方文档 文章内容精简掉了官方文档的一些比较浅显易懂的用法以及一些很细节的地方 一半是翻译 然后加入部分自己的理解 可以使读
  • 树莓派Linux内核替换

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 准备工作 二 修改配置文件 配置config 编译 打包 数据拷贝 将SD卡转插到树莓派 一 准备工作 安装好对应交叉编译工具 将需要替换的Linux拷进Ubu
  • python docx处理word文档中表格合并问题

    问题描述 python中用docx库读取word文件 若word文件中包含合并的表格表格 则通过docx读取显示 file docx Document path for table in file tables for row in tab
  • KVM上如何绑定虚拟机vcpu与物理CPU?

    Taskset命令设置某虚拟机在某个固定cpu上运行 1 设置某个进程pid在某个cpu上运行 root test taskset p000000000000000000000000000000000000100 95090 pid 950
  • 多节点高可用Eureka集群与服务注册

    0 多节点 找多借点配置的直接从最下面这里开始看 修改消费者和提供者的application yml文件 defaultZone http peer1 8761 eureka http peer2 8762 eureka 1 简介 Eure
  • list 去重方式

    List
  • 大专学历走社招,两个部门,六轮面试,终与字节无缘

    这个面试机会来的挺意外的 先在 Boss 投递的简历 后再某客网看到了内推人的微信 加了微信问了下进度 挂了 内推人给我打电话根据简历简单询问了一下情况 内推人很谦逊 毕业于一所 211 大学 和我说他的学历也很一般 然后和 hr 沟通捞了
  • IntelliJ IDEA运行JAVA

    1 安装软件 这边需要你先安装IntelliJ IDEA和java sdk 检查是否安装java sdk IntelliJ IDEA安装软件链接 https www jetbrains com idea download section w
  • Mac OSX创建动态链接库

    Windows DLL Linux so Mac OS X dylib dylib是Mach O格式 也就是Mac OS X下的二进制文件格式 Mac OS X提供了一系列 工具 用于创建和访问动态链接库 编译器 usr bin cc 也就
  • 服务器内存信息,查看linux服务器内存信息

    查看服务器内存信息 dmidecode grep P A5 Memory s Device grep Size email protected home dmidecode grep P A5 Memory s Device grep Si
  • shell 脚本中数字判断

    数字的判断 int1 eq int2 两数相等为真 int1 ne int2 两数不等为真 int1 gt int2 int1大于int2为真 int1 ge int2 int1大于等于int2为真 int1 lt int2 int1小于i
  • 代码随想录 - Day35 - 回溯:重新安排行程,棋盘问题

    代码随想录 Day35 回溯 重新安排行程 棋盘问题 332 重新安排行程 输入 tickets JFK SFO JFK ATL SFO ATL ATL JFK ATL SFO 输出 JFK ATL JFK SFO ATL SFO 解释 另