回溯专题的最后一章,有关游戏问题和一些其他问题。
(困难题暂放,会后续更新的)
棋盘问题
51. N皇后
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
解题思路
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]]
解题思路
这个递增子序列比较像是取有序的子集。而且本题也要求不能有相同的递增子序列。子集+去重,是不是不由自主的想起了刚刚讲过的 90.子集II。就是因为太像了,更要注意差别所在,要不就掉坑里了!
在90.子集II中我们是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组经行排序的,排完序的数组都是自增子序列了。所以不能使用之前的去重逻辑!
-
递归函数参数
本题求子序列,很明显一个元素不能重复使用,所以需要startIndex,调整下一层递归的起始位置。 -
终止条件
本题其实类似求子集问题,也是要遍历树形结构找每一个节点,所以和求子集问题类似,可以不加终止条件,startIndex每次都会+1,并不会无限递归。但本题收集结果有所不同,题目要求递增子序列大小至少为2。 -
单层搜索逻辑
在图中可以看出,同一父节点下的同层上使用过的元素就不能再使用。 -
优化
数组,set,map都可以做哈希表,而且数组干的活,map和set都能干,但如果数值范围小的话能用数组尽量用数组。
class Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
def backtrack(nums,startIndex):
repeat = [] #这里使用数组来进行去重操作
if len(path) >=2:
res.append(path[:]) #注意这里不要加return,要取树上的节点
for i in range(startIndex,len(nums)):
if nums[i] in repeat:
continue
if len(path) >= 1:
if nums[i] < path[-1]:
continue
repeat.append(nums[i]) #记录这个元素在本层用过了,本层后面不能再用了
path.append(nums[i])
backtrack(nums,i+1)
path.pop()
backtrack(nums,0)
return res