Leetcode题解 0015期

今天又跟人聊了一下天,感觉自己的速度实在有点慢,我应该更为抓紧一些,如果别人一边搞着研究,一遍还能每天刷三题的话,我那小小的自负心肯定就忍不住要多刷题喽,那么先从昨天的每日三题变成每日四题,这样子(另外明天的时间应该会多一点,所以相应的刷题也应该多一些,有空就刷题嘛,别弄那些乱七八糟的)

0051题 N皇后【N-Queens】

题目:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
这里写图片描述
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例:

输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

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

题目相对严谨

经典题目无需注意太多,输出格式注意一下

解题思路:
我们其实都知道当N很大的时候N皇后的解法会非常爆炸,所以这题的测量数据也不会那么多,但是位运算的写法不方便输出,所以这道题还是用标准的DFS,然后下一道题让输出结果,我们再用位运算,这里post代码:

class Solution:
    def __init__(self):
        self.res = []
        self.puzzle = []

    def display(self, queen_num):
        tmp_res = []
        for i in range(0, queen_num):
            k = self.puzzle[i]
            tmp_row = k*'.'+'Q'+(queen_num-k-1)*'.'
            tmp_res.append(tmp_row)
        self.res.append(tmp_res)

    def judge(self, s):
        for i in range(0,s):
            if self.puzzle[i] == self.puzzle[s] or abs(self.puzzle[i]-self.puzzle[s]) == abs(i-s):
                return False
        return True

    def queen(self, x, queen_num):
        for i in range(0, queen_num):
            self.puzzle[x] = i
            if self.judge(x):
                if x == queen_num-1:
                    self.display(queen_num)
                else:
                    self.queen(x+1, queen_num)

    def solveNQueens(self, n):
        self.puzzle = [0]*n
        self.queen(0,n)
        return self.res

然而当我看到最优解法是位运算的时候,我就有点后悔了,果然位运算还是能够实现输出的,只要中间保存p值即可,在这里post一下代码:

class Solution:
    def __init__(self):
        # self.sum = 0
        self.upperlim = 1
        self.result = []
        self.output_queen=[]

    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        self.upperlim = (1 << n) - 1
        self.queen(0, 0, 0)
        return self.output_queen

    def queen(self, row, ld, rd):
        if row != self.upperlim:
            pos = self.upperlim & ~(row | ld | rd)
            while pos:
                # p = pos & -pos
                p = pos & (~pos + 1)
                pos -= p
                self.result.append(p)
                self.queen(row + p, (ld + p) << 1, (rd + p) >> 1)
                self.result.pop()
        else:
            # self.sum += 1
            self.print_queen()

    def print_queen(self):
        le = len(self.result)
        out = []
        for i in range(le):
            tmp = self.result[i]
            # print(bin(tmp))
            count = 0
            while(tmp != 0):
                tmp = tmp >> 1
                count += 1
            out.append("."*(le-count) + "Q" + "."*(count-1))
        self.output_queen.append(out)

果然是大佬……╮(╯▽╰)╭


0052题 N皇后 II【N-Queens II】

题目:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回 n 皇后不同的解决方案的数量。

示例:

输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。

题目相对严谨

经典题目无需注意太多

解题思路:
这题就放心大胆的用位运算就好了,反正也没人拦着╮(╯▽╰)╭,和上一道题其实一样,就不post了。


0053题 最大子序和【Maximum Subarray】

题目:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
进价:如果你已经实现复杂度为 O ( n ) 的解法,尝试使用更为精妙的分治法求解。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

题目相对严谨

除Robust以外无需注意太多

解题思路:
哇塞这题上来一看,感觉就是线段树啊……诶,这题标的简单……嗯?为什么是简单,额,为什么我老想到线段树这么恐怖的东西……我可能疯了吧
这里post最好想的代码,首先就是因为如果前序和如果为负数的话,那么就已经可以从下一位直接计算了,因为已经为负数的区间是没有办法再往后延续的了,同时用另外一个数来保存最值即可,感觉这个sub_sumres是一段非常穷奥妙的使用。

class Solution:
    def maxSubArray(self, nums):
        n = len(nums)
        if n == 0: return 0
        res = nums[0]
        for i in range(0,n):
            res = max(res, nums[i])
        if res <= 0: return res
        sub_sum = 0
        res = 0
        for i in range(0, n):
            sub_sum += nums[i]
            sub_sum = max(sub_sum, 0)
            res = max(res, sub_sum)
        return res

进阶要求让编一个分治算法,那么按照分而治之的思想,这么考虑,一段序列从中间劈开,最大连续和出现位置一共有三种:1. 左边区间内;2. 右边区间内;3. 以中间节点为边界的左边最大和序列+以中间节点为边界的右边最大和序列,以这种思路来编分治算法:

class Solution:
    def solve(self, a, left, right):
        if left == right: return a[left]
        mid = (left + right) // 2
        maxLeft = self.solve(a, left, mid)
        maxRight = self.solve(a, mid+1, right)
        leftSum = a[mid]
        rightSum = a[mid+1]

        tmpSum = a[mid]
        for i in range(mid-1, left-1, -1):
            tmpSum += a[i]
            # tmpSum = max(tmpSum, 0)
            leftSum = max(leftSum, tmpSum)

        tmpSum = a[mid+1]
        for i in range(mid+2, right+1):
            tmpSum += a[i]
            # tmpSum = max(tmpSum, 0)
            rightSum = max(rightSum, tmpSum)

        return max(maxLeft, maxRight, leftSum+rightSum)

    def maxSubArray(self, nums):
        if len(nums) == 0: return 0
        return self.solve(nums, 0, len(nums)-1)

注意注释的两行,在搜索以中间为边界的最长子序列的时候不要用第一个方法中的取max,因为那样会把原来的负数变为0,从而增加,多加小心。
(这种分治比 O ( n ) 跑得慢是很正常的)


0054 螺旋矩阵【Spiral Matrix】

题目:
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例:

输入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

题目相对严谨

除Robust以外无需注意太多

解题思路:
这题不就是数字三角形,竟然还是中等难度的……╮(╯▽╰)╭
这么简单就不post代码了。

猜你喜欢

转载自blog.csdn.net/bright_silmarillion/article/details/80704014