LeetCode52-N皇后II

紧张到爆的数学考试昨天终于考完了

这几天真的是从早到晚不停的刷题啊

虽然最后的结果不是特别让自己满意

但还算得上对得起自己了

晚上回宿舍的路上

为了庆祝最后一门考试的结束

在一家小蛋糕店买了一盒网红蛋糕

 

最后结账的时候

那位阿姨店长扯出一个袋子给我套上蛋糕

我习惯性的说:不用袋子了

却没想到,她愣了一会儿

然后对我竖起大拇指

微笑的对我说:现在不找她拿袋子的人很少了

你以后要是当官,一定是位好官

听完之后,我也不好意思的笑了

庆兴的是自己在坚持的一些小事终于是得到了认可


52-N皇后II

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

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回 n 皇后不同的解决方案的数量。

示例:

输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

思路:

说实话,我觉得这题是道智障题目了,当然前提是上面的那道N皇后题目你做出来了。

程小新同学:LeetCode51-N皇后​zhuanlan.zhihu.com

做这道题之前如果对N皇后问题还不是很熟的朋友可以先看看我之前写的这篇文章,可以让你很快上手此类题目。如果这道N皇后题目你已经会做了,那么这道N皇后II题目那更是手到擒来了,因为你发现结果是让你求解法的数量,这不是在玷污我们智商嘛!最简单的就是用了len()函数就可以立即得出答案,完全没有技术含量。至于N皇后问题其中详细的步骤,我这儿就不讲了,在上述那个链接里面我讲的算是比较详细了,大家看看那个就行了,我就直接上代码吧。

class Solution:
    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 如果输入的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 len(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().totalNQueens(n)
    print(queen_list)

这当然是个最粗鲁的方法,所以执行效率比较低。

看到这个执行效率,心里还是有些低落的,为了缩短这个时间,我在题目字眼中不停地下功夫。恍然发现:这道题没有让我们求每种解法的具体表达形式,通俗点就是:最后你只需要告诉我有多少种解法就行,至于每种解法是怎样的我不care。所以按照这个思路我修改了部分代码,效率也是有所提升。

代码如下:

class Solution:
    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 如果输入的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:
                final_queens.append([])
                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 len(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().totalNQueens(n)
    print(queen_list)

代码其实很容易看懂,执行效率在40%左右,一般般吧!

如果各位读者有什么好的方法,也希望不吝赐教啊!!!

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习的学习者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值