LeetCode-题库-算法:51-60(Python)

51. N皇后

在这里插入图片描述
思路

  • 排除对应行,列和两个对角线的位置冲突:
    • 所在的行(cur)列(col)在上面行已经有皇后
    • 斜线上已存在皇后,斜线公式为
      正斜线: y = x y=x y=x,负斜线: y = − x y=-x y=x,则: y = ∣ x ∣ y=|x| y=x
      x 1 : c o l , y 1 : c u r , x 2 : A [ r o w ] , y 2 : r o w x_1:col, y_1:cur, x_2:A[row], y_2:row x1:col,y1:cur,x2:A[row],y2:row
      判断 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1, y_1), (x_2, y_2) (x1,y1),(x2,y2)是否在同一线上,则:
      y 1 − y 2 = ∣ x 1 − x 2 ∣ y_1-y_2 = |x_1-x_2| y1y2=x1x2


回溯函数queen(cur):

  • 从第一行cur = 0 开始
  • 循环列col放置皇后
    • 如果A[cur]不在攻击范围内(排除对应行,列和两个对角线的位置冲突)
      • 在A[cur]方格上放置皇后
      • 如果cur+1 == n,皇后填完,添加答案至ans中
      • 否则寻找下一行的解,queen(cur+1)
      • 回溯:A[cur]皇后位置清除
class Solution(object):
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        def attack(cur, col):
            for row in range(cur):
                if A[row] == col or cur - row == abs(col - A[row]):
                    return True
            return False

        def queen(cur=0):
            for col in range(n):
                if not attack(cur, col):
                    A[cur] = col
                    if cur + 1 == n:
                        temp = list()
                        for i in range(n):
                            # 如当n=4时,第一个答案为[1, 3, 0, 2],按返回格式赋值
                            temp.append('.'*A[i]+'Q'+'.'*(n-A[i]-1))
                        ans.append(temp)
                    else:
                        queen(cur+1)
                    A[cur] = None
            return 

        ans = list()
        A = [None]*n
        queen()
        return ans 



52. N皇后 II

在这里插入图片描述
思路
回溯函数queen(cur, count):

  • 从第一行cur = 0 开始
  • 循环列col放置皇后
    • 如果A[cur]不在攻击范围内(排除对应行,列和两个对角线的位置)
      • 在A[cur]方格上放置皇后
      • 如果cur+1 == n,皇后填完,count +=1
      • 否则寻找下一行的解,queen(cur+1, count)
      • 回溯:A[cur]皇后位置清除
class Solution(object):
    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        def attack(cur, col):
            for row in range(cur):
                if A[row] == col or cur - row == abs(col - A[row]):
                    return True
            return False

        def queen(cur=0, count=0):
            for col in range(n):
                if not attack(cur, col):
                    A[cur] = col
                    if cur + 1 == n:
                        count += 1
                    else:
                        count = queen(cur+1, count)
                    A[cur] = None
            return count
                    
        A = [None]*n
        return queen()



53. 最大子序和

在这里插入图片描述
思路
创建一个与数组等长的数组temp,记录nums对应位置的最大和,返回temp中的最大值

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nlen = len(nums)
        temp = [None]*nlen
        temp[0] = nums[0]
        i = 1
        while i < nlen:
            if temp[i-1] < 0:    # 当最大和为负数时
                temp[i] = nums[i]
            else:
                temp[i] = temp[i-1] + nums[i]
            i += 1
        return max(temp)



54. 螺旋矩阵

在这里插入图片描述
思路

  • 当列表为空,返回[]
  • 当列表只有一行,返回该行
  • 当列表只有一列,返回该列
  • 顺时针螺旋顺序添加元素至ans
    • 创建与matrix大小一致的trail列表跟踪足迹
    • dr为方向,0:向右(c+1),1:向下(r-1),2:向左(c-1),3.向上(r+1)
    • 共有m*n个数,顺时针螺旋顺序添加matrix的元素至ans,已添加的位置trail[r][c]==True
    • 顺时针螺旋顺序:
      • 判断到边际的点(右上角(0, n-1),右下角(m-1, n-1),左下角(m-1, 0))或下一步是已走过的路(trail[r][c]==True)时改变方向
class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        ans = list()
        if not matrix:
            return []
        if len(matrix) == 1:
            return matrix[0]
        if len(matrix[0]) == 1:
            for i in range(len(matrix)):
                ans.append(matrix[i][0])
            return ans
        m = len(matrix)    # row
        n = len(matrix[0])    # column
        trail = [[False]*n for _ in range(m)]    # 未走的路为False,已走为True
        r, c, dr = 0, 0, 0
        for _ in range(m*n):
            ans.append(matrix[r][c])
            trail[r][c] = True
            if dr%4 == 0:
                c += 1
                if c == n-1 or trail[r][c+1]:
                    dr += 1 
            elif dr%4 == 1:
                r += 1
                if r == m - 1 or trail[r+1][c]:
                    dr += 1
            elif dr%4 == 2:
                c -= 1
                if c == 0 or trail[r][c-1]:
                    dr += 1
            else:
                r -= 1
                if trail[r-1][c]:
                    dr += 1   
        return ans



55. 跳跃游戏

在这里插入图片描述
思路
贪心

  1. 初始化end,maxindex为0
  2. end为当前能到达的最大位置,maxindex在i到end途中时,寻找能到达的最大位置
  3. 当i==end时,更新end为maxindex
  4. 如果end能到达end走到等于nums或大于nums最后一个位置,则完成跳跃,否则,不能到达nums最后一个位置
class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums or len(nums) == 1:
            return True
        nlen = len(nums)
        end, maxindex = 0, 0
        for i in range(nlen - 1):
            maxindex = max(i + nums[i], maxindex)
            if i == end:
                end = maxindex
                if end >= nlen - 1:
                    return True
        return False



56. 合并区间

在这里插入图片描述
思路

  1. 根据intervals的第一个数进行排序
  2. 当ans=[]或interval第一个数大于ans里最后即最大的数时(如:ans[[1, 6], interval=[8, 10]),添加interval进ans中
  3. 当interval第一个数小于ans最后一个数时(如:ans=[1, 3],interval=[2, 6], 更新ans[-1][1]=interval[1]),更新ans最后的数
class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        intervals.sort(key=lambda x:x[0])

        ans = list()
        for interval in intervals:
            if not ans or interval[0] > ans[-1][1]:    
                ans.append(interval)
            else:
                ans[-1][1] = max(ans[-1][1], interval[1])
        return ans



57. 插入区间

在这里插入图片描述
思路
将newInterval插入intervals中后,使用56题的方法进行合并区间

class Solution(object):
    def insert(self, intervals, newInterval):
        """
        :type intervals: List[List[int]]
        :type newInterval: List[int]
        :rtype: List[List[int]]
        """
        intervals.append(newInterval)
        intervals.sort(key=lambda x:x[0])
        ans = list()
        for interval in intervals:
            if not ans or interval[0] > ans[-1][1]:
                ans.append(interval)
            else:
                ans[-1][1] = max(ans[-1][1], interval[1])
        return ans



58. 最后一个单词的长度

在这里插入图片描述
思路

  1. 去除字符串前后空格
  2. 从字符串后面开始计算,如果是字母长度加1,如果不是,结束循环
class Solution(object):
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        s = s.strip()
        end = len(s) - 1
        count = 0
        while end >= 0:
            if s[end].isalpha():
                count += 1
            else:
                break
            end -= 1
        return count

思路

  1. 去除字符串前后空格
  2. 以空格分隔的单词保存在ans中,返回最后一个单词的长度
class Solution(object):
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        s = s.strip()
        ans = s.split(' ')[-1]
        return len(ans)



59. 螺旋矩阵 II

在这里插入图片描述
思路

  1. 当n=1,返回[[1]]
  2. 顺时针螺旋顺序添加正整数至ans
    • 创建与matrix大小一致的trail列表跟踪足迹
    • dr为方向,0:向右(c+1),1:向下(r-1),2:向左(c-1),3.向上(r+1)
    • 共有n*n个数,顺时针螺旋顺序添加正整数至ans,已添加的位置trail[r][c]==True
    • 顺时针螺旋顺序:
      • 判断到边际的点(右上角(0, n-1),右下角(n-1, n-1),左下角(n-1, 0))或下一步是已走过的路(trail[r][c]==True)时改变方向
class Solution(object):
    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        if n == 1:
            return [[1]]
        ans = [[0]*n for _ in range(n)]
        trail = [[False]*n for _ in range(n)]
        r, c, dr, tar = 0, 0, 0, n*n+1
        for num in range(1, tar):
            ans[r][c] = num
            trail[r][c] = True
            if dr%4 == 0:    # 向右
                c += 1
                if c == n - 1 or trail[r][c+1]:
                    dr += 1
            elif dr%4 == 1:    # 向下
                r += 1
                if r == n - 1 or trail[r+1][c]:
                    dr += 1
            elif dr%4 == 2:    # 向左
                c -= 1
                if c == 0 or trail[r][c-1]:
                    dr += 1
            else:    # 向上
                r -= 1
                if trail[r-1][c]:
                    dr += 1
        return ans

思路

  1. 从左到右添加正整数,添加一行后,往下移动一行
  2. 从上往下添加正整数,添加一列后,往左移动一列
  3. 从右往左添加正整数,添加一行后,往上移动一行
  4. 从下往上添加正整数,添加一列后,往右移动一列
class Solution(object):
    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        ans = [[0]*n for _ in range(n)]
        l, r, u, d, num, tar = 0, n-1, 0, n-1, 1, n*n+1
        while num < tar:
            for i in range(l, r+1):    # 从左到右
                ans[u][i] = num
                num += 1
            u += 1    # 往下移动一行
            for i in range(u, d+1):    # 从上往下
                ans[i][r] = num
                num += 1
            r -= 1    # 往左移动一列
            for i in range(r, l-1, -1):    # 从右往左
                ans[d][i] = num
                num += 1
            d -= 1    # 往上移动一行
            for i in range(d, u-1, -1):    # 从下往上
                ans[i][l] = num
                num += 1
            l += 1    # 往右移动一列
        return ans



60. 第k个排列

在这里插入图片描述
思路

  1. 全序列的排序其实和阶乘是一样的,创建一个阶乘函数factorial(n)
  2. 创建集合nums = [1, 2, 3, …, n]
  3. 第一位数在n个数中选取,每位数后面有(n-1)!种排序。第二位在n-1个数中选取,每位数后面有(n-2)!种排序…因此全序列有n*(n-1)*(n-2)!=n!种排序。因为index由0开始,根据第k个排序选取nums中的数字,因此k=k-1。如n=3,k=2,共有n!=3!=6种排序,第0个序列为123(k=1),第1个序列为132(k=2)…
    • 选择第一位数, index=k//(n-1)!=1//(3-1)!=1//2=0,选取nums[0]=1。因为已选取第一位数,位置已经移位至第index*(n-1)!,所以更新k=k-index*(n-1)=1-0*(3-1)!=1。k=k%(n-1)!=1%(3-1)!=1得到的结果一样。将第一位数添加至 ans=[1]。nums中去除已选的第一位数得到nums=[2, 3]。nums剩下2位数,更新n=n-1=3-1=2。
    • 选择第二位数,index=k//(n-1)!=1//(2-1)!=1,选取nums[1]=3。更新k=k%(n-1)!=1%(2-1)!=0,ans=[1, 3],nums=[2],n=n-1=2-1=1。
    • 选取第三位数,index=k//(n-1)!=0//(1-1)!=0,选取nums[0]=2。更新k=k%(n-1)!=0%(1-1)!=0,ans=[1, 3, 2],nums=[],n=n-1=1-1=0,结束循环,返回ans。
k123
1123
2132
3213
4231
5312
6321
class Solution(object):
    def getPermutation(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: str
        """
        def factorial(n):
            if n == 0 or n == 1:
                return 1
            temp = 1
            for i in range(2, n+1):
                temp *= i
            return temp
        nums = [x for x in range(1, n+1)]
        ans = ""
        k -= 1
        while n > 0:
            fac = factorial(n-1)
            index = k//fac
            k %= fac
            ans += str(nums[index])
            nums = nums[0:index] + nums[index+1:]
            n -= 1
        return ans
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值