代码随想录算法训练营第三十天|491. 非递减子序列,46. 全排列,47. 全排列 II,332. 重新安排行程,51. N 皇后,37. 解数独

news2024/11/28 18:51:38

491. 非递减子序列,46. 全排列,47. 全排列 II,332. 重新安排行程,51. N 皇后,37. 解数独

    • 491. 非递减子序列
    • 46. 全排列
    • 47. 全排列 II
    • 332. 重新安排行程
    • 51. N 皇后
    • 37. 解数独

491. 非递减子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

示例 1
输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

示例 2
输入:nums = [4,4,3,2,1]
输出:[[4,4]]

注意这道题数组不能排序,会破坏数组结构。有重复元素在同一图层的情况,则同一父节点下的同层上使用过的元素就不能再使用了,参考代码使用数组来进行去重操,记录本层元素是否重复使用,新的一层uset都会重新定义(清空),所以要知道uset只负责本层

tips:是否增加return是判断是否输出到叶节点。回溯题目在做时候,先画树便于理解,注意同一图层和同一分支元素是哪里生效的,下面一题增加了同一分支的判断。

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        result = []
        self.backtracking(nums,0,[],result)
        return result    
    
    def backtracking(self,s,index,path,result):
        if  len(path)>1:
            result.append(path[:])
        used = [0] * 201  # 使用数组来进行去重操作,题目说数值范围[-100, 100]
        for i in range(index,len(s)):           
            if (path and s[i] < path[-1]) or used[s[i] + 100] == 1:
                continue  # 如果当前元素小于上一个元素,或者已经使用过当前元素,则跳过当前元素
            
            used[s[i] + 100] = 1  # 标记当前元素已经使用过
            path.append(s[i])  # 将当前元素加入当前递增子序列
            self.backtracking(s, i + 1, path, result)
            path.pop()

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2
输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3
输入:nums = [1]
输出:[[1]]
全排列,每次回溯从0开始,增加一个判断当前节点是否遍历过的判断,可使用字典或索引列表,下面是使用字典的例子,当前遍历值在输出数字 p a t h path path中则跳过。最终输出结果是 p a t h path path数组长度等于原数组长度。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        result = []
        self.backtracking(nums,0,[],result)
        return result    
    
    def backtracking(self,s,index,path,result):
        if  len(path)==len(s):
            result.append(path[:])  
        for i in range(index,len(s)):  
            if s[i] in path:
                continue
            path.append(s[i])  
            self.backtracking(s, 0, path, result)
            path.pop()

参考代码用use数组记录是否使用。

class Solution:
    def permute(self, nums):
        result = []
        self.backtracking(nums, [], [False] * len(nums), result)
        return result

    def backtracking(self, nums, path, used, result):
        if len(path) == len(nums):
            result.append(path[:])
            return
        for i in range(len(nums)):
            if used[i]:
                continue
            used[i] = True
            path.append(nums[i])
            self.backtracking(nums, path, used, result)
            path.pop()
            used[i] = False

47. 全排列 II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1
输入:nums = [1,1,2]
输出
[[1,1,2],
[1,2,1],
[2,1,1]]

示例 2
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

增加一个数组记录索引,同一图层重复元素判断用判断回溯重复数字的used数组。

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        result = []
        nums.sort()
        self.backtracking(nums,[],[],result)
        return result    
    
    def backtracking(self,s,path,root,result):
        if  len(path)==len(s):
            result.append(path[:]) 
            return result
        used = [0]* 20
        for i in range(len(s)):  
            if i in root or used[s[i]+10]==1:
                continue
            path.append(s[i])  
            root.append(i)
            used[s[i]+10]=1
            self.backtracking(s, path, root,result)           
            path.pop()
            root.pop()

参考代码,只用一个数组进行回溯,注意跳过循环的情况。

class Solution:
    def permuteUnique(self, nums):
        nums.sort()  # 排序
        result = []
        self.backtracking(nums, [], [False] * len(nums), result)
        return result

    def backtracking(self, nums, path, used, result):
        if len(path) == len(nums):
            result.append(path[:])
            return
        for i in range(len(nums)):
            if (i > 0 and nums[i] == nums[i - 1] and not used[i - 1]) or used[i]:
                continue
            used[i] = True
            path.append(nums[i])
            self.backtracking(nums, path, used, result)
            path.pop()

接下来是回溯题目几道比较难的应用,先学习一下思路。

332. 重新安排行程

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。

  • 例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前。

假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

示例 1
输入:tickets = [[“MUC”,“LHR”],[“JFK”,“MUC”],[“SFO”,“SJC”],[“LHR”,“SFO”]]
输出:[“JFK”,“MUC”,“LHR”,“SFO”,“SJC”]

示例 2
输入:tickets = [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释:另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”] ,但是它字典排序更大更靠后。

class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        self.adj = {}

        # sort by the destination alphabetically
        # 根据航班每一站的重点字母顺序排序
        tickets.sort(key=lambda x:x[1])

        # get all possible connection for each destination
        # 罗列每一站的下一个可选项
        for u,v in tickets:
            if u in self.adj: self.adj[u].append(v)
            else: self.adj[u] = [v]

        # 从JFK出发
        self.result = []
        self.dfs("JFK")  # start with JFK

        return self.result[::-1]  # reverse to get the result

    def dfs(self, s):
        # if depart city has flight and the flight can go to another city
        while s in self.adj and len(self.adj[s]) > 0:
            # 找到s能到哪里,选能到的第一个机场
            v = self.adj[s][0]  # we go to the 1 choice of the city
            # 在之后的可选项机场中去掉这个机场
            self.adj[s].pop(0)  # get rid of this choice since we used it
            # 从当前的新出发点开始
            self.dfs(v)  # we start from the new airport

        self.result.append(s)  # after append, it will back track to last node, thus the result list is in reversed order

51. N 皇后

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

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

示例 1
输入:n = 4
输出:[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…Q.”,“Q…”,“…Q”,“.Q…”]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2
输入:n = 1
输出:[[“Q”]]

回溯经典应用N皇后问题,主要是isValid函数。判断当前位置插入是否有效,终止条件是遍历到最后一行或一列,此时判断已经插入的棋子数量,决定输出。

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        chessboard = ['.' * n for _ in range(n)]  # 初始化棋盘
        result = []
        path = []
        self.dfs(n, result, path, 0, 0, chessboard)
        return result

    def dfs(self, n, result, path, istart, j, chessboard):
        if istart == n or j == n:
            if len(path) == n:
                result.append(chessboard[:])
        for i in range(istart, n):
            for j in range(n):
                if self.isValid(n, i, j, path):
                    chessboard[i] = chessboard[i][:j] + 'Q' + chessboard[i][j + 1:]
                    path.append([i, j])
                    self.dfs(n, result, path, i + 1, j, chessboard)
                    chessboard[i] = chessboard[i][:j] + '.' + chessboard[i][j + 1:]
                    path.pop()

    def isValid(self, n, i, j, path):
        for t in path:
            if t[0] == i or t[1] == j:
                return False
        ii, jj = i - 1, j - 1
        # 检查 45 度角是否有皇后
        while ii >= 0 and jj >= 0:
            if [ii, jj] in path:
                return False  # 左上方向已经存在皇后,不合法
            ii -= 1
            jj -= 1
        # 检查 135 度角是否有皇后
        ii, jj = i - 1, j + 1
        while ii >= 0 and jj < n:
            if [ii, jj] in path:
                return False  # 右上方向已经存在皇后,不合法
            ii -= 1
            jj += 1
        return True

附参考代码

class Solution:
    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]  # 返回结果集

    def backtracking(self, n: int, row: int, chessboard: List[str], result: List[List[str]]) -> None:
        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 isValid(self, row: int, col: int, chessboard: List[str]) -> bool:
        # 检查列
        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  # 当前位置合法

37. 解数独

编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1
在这里插入图片描述
输入:board = [[“5”,“3”,“.”,“.”,“7”,“.”,“.”,“.”,“.”],
[“6”,“.”,“.”,“1”,“9”,“5”,“.”,“.”,“.”],
[“.”,“9”,“8”,“.”,“.”,“.”,“.”,“6”,“.”],
[“8”,“.”,“.”,“.”,“6”,“.”,“.”,“.”,“3”],
[“4”,“.”,“.”,“8”,“.”,“3”,“.”,“.”,“1”],
[“7”,“.”,“.”,“.”,“2”,“.”,“.”,“.”,“6”],
[“.”,“6”,“.”,“.”,“.”,“.”,“2”,“8”,“.”],
[“.”,“.”,“.”,“4”,“1”,“9”,“.”,“.”,“5”],
[“.”,“.”,“.”,“.”,“8”,“.”,“.”,“7”,“9”]]
输出:[[“5”,“3”,“4”,“6”,“7”,“8”,“9”,“1”,“2”],
[“6”,“7”,“2”,“1”,“9”,“5”,“3”,“4”,“8”],
[“1”,“9”,“8”,“3”,“4”,“2”,“5”,“6”,“7”],
[“8”,“5”,“9”,“7”,“6”,“1”,“4”,“2”,“3”],
[“4”,“2”,“6”,“8”,“5”,“3”,“7”,“9”,“1”],
[“7”,“1”,“3”,“9”,“2”,“4”,“8”,“5”,“6”],
[“9”,“6”,“1”,“5”,“3”,“7”,“2”,“8”,“4”],
[“2”,“8”,“7”,“4”,“1”,“9”,“6”,“3”,“5”],[“3”,“4”,“5”,“2”,“8”,“6”,“1”,“7”,“9”]]
解释:输入的数独如上图所示,唯一有效的解决方案如下所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2206440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

技术成神之路:设计模式(二十)装饰模式

介绍 装饰模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许在不改变对象自身的情况下&#xff0c;动态地为对象添加额外的职责。这个模式通常用于增强或改变对象的功能。 1.定义 装饰模式通过创建一个装饰类&#xff0c;将功能动态地添加…

网站设计公司怎么评估?2024网站定制公司哪家好

在选择一家网站建设公司时&#xff0c;需要采取一些筛选方法来评估其能力和专业性。可以通过查看公司的案例展示、项目经验、团队规模等方面来评估公司的实力。同时&#xff0c;需要了解公司是否有与自己业务相似的项目经验&#xff0c;以便更好地满足自己的需求。在选择公司时…

win0删除 Windows.old

参考&#xff1a;https://blog.csdn.net/xitongzhijia_abc/article/details/126270452 win10如下所示&#xff1a; 打开 设置–>系统—>存储

Ps:PDF 演示文稿

Ps菜单&#xff1a;文件/自动/PDF 演示文稿 Automate/PDF Presentation PDF 演示文稿 PDF Presentation命令提供了创建 PDF 演示文稿的多种选项&#xff0c;用户可以添加当前打开的文件或手动选择文件&#xff0c;选择背景颜色、字体大小等&#xff0c;设置演示文稿的页面切换间…

哪个牌子充电宝性价比高?2024年精选性价比排行榜充电宝推荐

在数字化生活日益普及的今天&#xff0c;充电宝作为我们移动设备的“能量加油站”&#xff0c;其重要性不言而喻。无论是商务出行、旅行探险还是日常通勤&#xff0c;一款性价比高、安全可靠的充电宝都是不可或缺的伴侣。然而&#xff0c;面对市场上琳琅满目的充电宝品牌与型号…

芯课堂 | Synwit_UI_Creator(μgui)平台之图像处理篇

今天小编给大家介绍的是UI_Creator&#xff08;μgui&#xff09;平台下关于图像处理的选项。 UI_Creator&#xff08;μgui&#xff09;平台图片类控件有图像控件和分级图像控件&#xff0c;均包含以下选项&#xff1a; 1、消除水波纹&#xff1a; 由于16位真彩色&#xff08…

MySQL常用语句(二)

#数据修改 #insert insert语句用于将一行或多行插入到表中。insert语句的语法&#xff1a; 在insert into子句之后的括号内指定表名和逗号分隔列的列表&#xff0c;然后将括号内相应列的逗号分隔值放在values关键字之后。创建一个名为tasks的新表来练习insert语句&#xff1a…

火山引擎边缘智能×扣子,拓展AI Agent物理边界

9月21日&#xff0c; 火山引擎边缘智能扣子技术沙龙在上海圆满落地&#xff0c;沙龙以“探索端智能&#xff0c;加速大模型应用”为主题&#xff0c;边缘智能、扣子、地瓜机器人以及上海交大等多位重磅嘉宾出席&#xff0c;分享 AI 最新趋势及端侧大模型最新探索与应用实践。 …

C++继承深度剖析:从理论到实践的跨越

✨✨小新课堂开课了&#xff0c;欢迎欢迎~✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C&#xff1a;由浅入深篇 小新的主页&#xff1a;编程版小新-CSDN博客 前言&#xff1a; 前面我们已经学了很多有关…

纠删码参数自适应匹配问题ECP-AMP实验方案(中)

6.方法设计 6.1.数据获取 为了收集不同的文件大小和纠删码参数对性能指标的影响&#xff0c;本文在Hadoop平台上进行了模拟实验。Hadoop是一种开源的分布式存储和计算框架&#xff0c;它可以支持不同类型的纠删码&#xff0c;并提供了一些应用程序接口和工具来测试和评估纠删…

Rstudio 绘制elecdaily的时序图与预测

&#xff08;1&#xff09;绘制上述数据的时序图并将温度作为解释变量对日度耗电量建模。为什么是它们之间是正向相关关系&#xff1f; head(elecdaily,20) %>% as.data.frame() %>% ggplot(aes(xTemperature, yDemand)) ylab("电量能耗 %") xlab("温度…

论文笔记:D-vlog 用于抑郁症检测的多模态数据集

整理了AAAI2022 D-vlog: Multimodal Vlog Dataset for Depression Detection 论文的阅读笔记 背景方法特征提取模型 实验数据集主实验不同模态的性能性别的影响 背景 以往关于抑郁症检测的工作大多集中在实验室环境下对抑郁症个体的检测&#xff0c;难以在实践中推广。本文提出…

Java之API

前言 这一篇讲API&#xff0c;有很多很多的API 1. Object 它是所有类的祖宗类&#xff0c;所以任何类都可以直接使用Object的一些方法 1.1 toString 从这个我们就可以看出&#xff0c;平时对s1的打印其实是默认调用了它的toString函数&#xff0c;因为toString是灰色的 但…

qt数据库的系统

pro文件 QT core gui sqlgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Plea…

四款电脑录屏的软件,谁更胜一筹?

作为一名喜欢搜罗各种办公软件的打工人&#xff0c;我每天的工作都离不开电脑&#xff0c;而录屏软件就成了我工作中不可或缺的小帮手。最近&#xff0c;我试用了四款流行的录屏软件&#xff0c;今天就来跟大家分享一下我的使用感受&#xff0c;看看哪款软件更得我心。 一、福…

Python和C++及MATLAB低温磁态机器学习模型

&#x1f3af;要点 使用小规模磁态训练模型&#xff0c;并在二维三维爱德华兹-安德森模型上使用四种算法测试&#xff1a;贪婪算法、模拟退火算法、并行回火算法和本模型。将磁态基态搜索视为马尔可夫决策过程 (MDP)&#xff0c;学习最优策略以累积其最大回报。设计图神经网络…

从0开始深度学习(9)——softmax回归的逐步实现

文章使用Fashion-MNIST数据集&#xff0c;做一次分类识别任务 Fashion-MNIST中包含的10个类别&#xff0c;分别为&#xff1a; t-shirt&#xff08;T恤&#xff09;、trouser&#xff08;裤子&#xff09;、pullover&#xff08;套衫&#xff09;、dress&#xff08;连衣裙&…

SSD |(二)SSD主控

文章目录 &#x1f4da;控制器架构&#x1f407;PCIe和NVMe控制器前端子系统&#x1f407;NAND闪存控制器后端子系统&#x1f407;内存子系统&#x1f407;安全子系统&#x1f407;CPU计算子系统 &#x1f4da;控制器架构 控制器作为一个片上系统&#xff0c;处理来自用户端的…

Linux下的Makefile基本操作

1.Makefile与 make介绍 在Linux中&#xff0c; Makefile 是⼀个⽂件&#xff0c; 令会在当前⽬录下找 make 是⼀个指令&#xff0c;当使⽤ Makefile ⽂件从⽽执⾏内部的内容 2.创建第一个 Makefile并使用make ⾸先&#xff0c;在当前⽬录下创建⼀个makefile文件 接下来在同级…

【小工具分享】下载保存指定网页的所有图片

一、保存百度首页所有的图片 先看一下保存的图片情况 二、思路 1、打开网页 2、获取所有图片 3、依次下载保存图片到指定路径 三、完整代码 from selenium import webdriver from selenium.webdriver.common.by import By b webdriver.Firefox() import urllib.request…