[Leetcode/Python3] 第204场周赛题解

P1 重复至少 K 次且长度为 M 的模式

给你一个正整数数组 arr,请你找出一个长度为 m 且在数组中至少重复 k 次的模式。

模式 是由一个或多个值组成的子数组(连续的子序列),连续 重复多次但 不重叠 。 模式由其长度和重复次数定义。

如果数组中存在至少重复 k 次且长度为 m 的模式,则返回 true ,否则返回 false 。

解:

  1. 数组不支持hash,转化为字符串就好了
class Solution:
    def containsPattern(self, arr: List[int], m: int, K: int) -> bool:
        def hashcode(A):
            return ",".join(map(str, A))
        n = len(arr)
        s = hashcode(arr)
        for i in range(n):
            j = i + m
            if j > n:
                break
            if hashcode(arr[i:j] * K) in s:    
                return True
        
        return False

P2 乘积为正数的最长子数组长度

给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。

一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。

请你返回乘积为正数的最长子数组长度。

解:

  1. 数一数,遇到0重置。
class Solution:
    def getMaxLen(self, nums: List[int]) -> int:
        if not nums: return 0 
        def sign(x):
            if x > 0: return 1
            if x == 0 : return 0
            return -1
        n = len(nums)
        pos, neg, acc = -1, n, 1
        ret = 0
        for i, x in enumerate(nums):
            acc *= sign(x)
            if acc == 0:
                pos, neg, acc = i, n, 1
            elif acc < 0:
                if neg == n:
                    neg = i
                else:    
                    ret = max(ret, i - neg)
            else:        
                ret = max(ret, i-pos)
        return ret

P3 使陆地分离的最少天数

给你一个由若干 0 和 1 组成的二维网格 grid ,其中 0 表示水,而 1 表示陆地。岛屿由水平方向或竖直方向上相邻的 1 (陆地)连接形成。

如果 恰好只有一座岛屿 ,则认为陆地是 连通的 ;否则,陆地就是 分离的 。

一天内,可以将任何单个陆地单元(1)更改为水单元(0)。

返回使陆地分离的最少天数。

解:

  1. 分析, 最多2次。对左上角的点, 移掉右边和下边的点,它就一定是分离的。
  2. 判断是否是0次,1次。
  3. 判断是否1次可以用Tarjan算法, Tarjan算法,还不会写,会了之后,再总结一下。
class DSU:
    def __init__(self, N):
        self.parent = [x for x in range(N)]

    def find(self, x):
        if self.parent[x] == x:
            return x
        else:
            # path compression
            ret = self.find(self.parent[x])
            self.parent[x] = ret
            return ret

    def union(self, x, y):
        # px == self.parent[px]
        px = self.find(x)
        py = self.find(y)
        self.parent[px] = self.parent[py]

class Solution:
    def minDays(self, grid: List[List[int]]) -> int:
        if not self.isconnect(grid): return 0
        n, m = len(grid), len(grid[0])
        for i in range(n):
            for j in range(m):
                if grid[i][j] == 1:
                    grid[i][j] = 0
                    if not self.isconnect(grid):
                        return 1
                    grid[i][j] = 1
        return 2            
                    
    def isconnect(self, grid: List[List[int]]) -> bool:
        n, m = len(grid), len(grid[0])
        N = n*m
        dsu = DSU(N)
        def idx(i, j): return i*m + j
        for i in range(n):
            for j in range(m):
                if grid[i][j] == 0: continue
                for dx, dy in [[1,0],[-1,0],[0,1],[0,-1]]:
                    ni, nj = i+dx, j + dy
                    if 0 <= ni < n and 0 <= nj <m and grid[ni][nj] == 1:
                        dsu.union(idx(i,j), idx(ni, nj))
        parent = set()                
        for i in range(n):
            for j in range(m):
                if grid[i][j] == 1:
                    parent.add(dsu.find(idx(i, j)))
                    
        return len(parent) == 1

P4 将子数组重新排序得到同一个二叉查找树的方案数

给你一个数组 nums 表示 1 到 n 的一个排列。我们按照元素在 nums 中的顺序依次插入一个初始为空的二叉查找树(BST)。请你统计将 nums 重新排序后,统计满足如下条件的方案数:重排后得到的二叉查找树与 nums 原本数字顺序得到的二叉查找树相同。

比方说,给你 nums = [2,1,3],我们得到一棵 2 为根,1 为左孩子,3 为右孩子的树。数组 [2,3,1] 也能得到相同的 BST,但 [3,2,1] 会得到一棵不同的 BST 。

请你返回重排 nums 后,与原数组 nums 得到相同二叉查找树的方案数。

由于答案可能会很大,请将结果对 10^9 + 7 取余数。

解:

  1. 模拟快排过程, pivot选第一个数。
  2. 计算的话, 就是用到组合数 C n k C_n^k Cnk。阶乘运算会重复很多次,开个表记录一下。 这样算的就比较快了(不知道不开表会不会TLE)。
class Solution:
    def numOfWays(self, nums: List[int]) -> int:
        n = len(nums)
        mod = 10 **9 + 7
        self.T = [1]*(n + 1)
        for i in range(1, n + 1):
            self.T[i] = self.T[i-1] *i
        return (self.F(nums) - 1) % mod
    def C(self, n, k):
        return self.T[n] // self.T[n-k] // self.T[k]
    def F(self, nums: List[int]) -> int:
        if not nums or len(nums) == 1: return 1
        pivot = nums[0]
        A, B = [], []
        for x in nums[1:]:
            if x > pivot: A.append(x)
            if x < pivot: B.append(x)
        n, m = len(A), len(B)        
        return self.C(n+m, m) * self.F(A) * self.F(B)   

你可能感兴趣的:(python3,leetcode周赛)