昨天的英语考试终于是考完了啊
为了这门考试
我可是什么都豁出去了啊
复习资料打印了一大堆
凡是能够得到的资料都打印了
具体见下图
昨天早上还特地6点半就爬起床了
为了就是多看课本一眼
昨天的考试果然也没辜负我的辛苦努力
呜呜呜,大家快夸我,快夸我
啊哈哈哈哈哈哈哈哈哈!!!
51-N皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
思路:
如果看过我之前写的文章的朋友,看到这一题心里肯定乐开了花,因为我之前就一直给大家灌输回溯法的吊炸天的好处,并且还总结了一篇关于回溯法求解的文章,具体如下:
程小新同学:LeetCode--回溯法心得zhuanlan.zhihu.com
在这篇文章里我就特地给出了关于N皇后的例子,因为实在是太经典了,并且相应给出了其解法。这两题唯一不同的就是最后N皇后组合情况的表示形式不一样罢了,其他的过程基本上是一摸一样了。但在这里,我还是想针对这题好好讲讲回溯的思路,我们总是讲回溯回溯,那它的核心是什么呢?搞清楚了这个你才能很快很好的利用这个方法解题。我总结的核心就是:当前递归的值一定能够回到其对应的上一次递归操作的值,只有能将当前值改成上一次操作的值,才能继续遍历操作,其实这个思想有点像暴力搜索。这不过这个是剪枝了的暴力搜索,当你发现某一次递归操作中的值不符合条件的时候,后面的递归操作也就不必进行了,直接回溯到上一个值并修改上一个值,继续进行递归操作。说了这么多,可能有些人已经晕了,可以看看我画的这张图,方便大家理解。
最后再多嘴一句:回溯算法其实就是模拟我们大脑思考相应问题的主流套路,对所有情况组成的树进行剪枝操作。
代码如下:
class Solution:
# 关于这一题,我在之前写的一篇文章回溯法里写到了相应的解法,只不过答案的表达方式不同
# N皇后问题算是特别经典的回溯法求解问题了
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
# 如果输入的n值(也就是棋盘大小的维度)小于0,这就是没意义了
if n <= 0:
return []
# 定义保存每种解法的列表集合
final_queens = []
# 核心的递归函数
def back(n_queen_list=[], current_row=0, queen_pos=[]):
"""
:param n_queen_list: [[str]]-->用来存放每种符合要求情况下的皇后安置情况
:param current_row: [int, int]-->用来指定当前皇后安放的位置(假设)不一定是最后安置的情况
:param queen_pos: [[int, int]]-->专门用来保存所有皇后的坐标,方便查重函数conflict()的比较
:return: None
"""
# 出口条件,如果最后一行的皇后放置好了,说明答案也出来了
if len(n_queen_list) == n:
# 因为题目要求最终每一行的位置都是用一串字符串表示,所以这里得转换
answer_list = []
for index in n_queen_list:
answer_list.append(''.join(index))
final_queens.append(answer_list)
return True
# 这里其实是对于当前行current_row每一列遍历查找符合要求的皇后位置
for queen_col in range(n):
# 指定准备用来检测的皇后位置
current_queen = [current_row, queen_col]
# 如果指定的皇后位置与之前安置的皇后位置上没有冲突,说明可以进行下一步递归检测,否则继续查找
if self.conflict(queen_pos, current_queen) is False:
new_queen = ['.']*n
new_queen[queen_col] = 'Q'
# 这儿主要是记得保存当前位置,方便回溯
back(n_queen_list+[new_queen], current_row + 1, queen_pos + [current_queen])
back()
return final_queens
# 检测皇后之间的位置关系
def conflict(self, queen_pos, current_queen):
"""
:param queen_pos: [[]]-->指代当前皇后存放之前的所有皇后的集合
:param current_queen: []-->指代当前皇后想要存放的位置
:return:Flag: boolean-->指代当前位置的皇后是否与之前所有位置的皇后有冲突
"""
# 此处的queen_length既是之前保存的queen_list集合的长度,也可以理解为当前current_queen皇后的行下标
queen_length = len(queen_pos)
if queen_length == 0:
return False
# 定义是否有位置冲突的标签
Flag = False
for index in range(queen_length):
# queen_length - index主要是控制相邻两行的皇后不能处于对角线上,其他的就没要求
if abs(current_queen[1] - queen_pos[index][1]) in (0, queen_length - index):
Flag = True
break
return Flag
if __name__ == "__main__":
n = 4
queen_list = Solution().solveNQueens(n)
print(queen_list)
执行效率属于中等吧,在50%左右。