LeetCode笔记:Biweekly Contest 60

1. 题目一

给出题目一的试题链接如下:

1. 解题思路

这一题思路挺直接的,就是找到某个元素左侧的元素之和恰好等于右侧的元素之和即可。

而后者则可以通过总的元素之和减去当前元素以及其自身求得。

综上我们就可以快速得到答案。

2. 代码实现

给出python代码实现如下:

class Solution:
    def findMiddleIndex(self, nums: List[int]) -> int:
        n, tot = len(nums), sum(nums)
        s = 0
        for i in range(n):
            if 2*s == tot-nums[i]:
                return i
            s += nums[i]
        return -1

提交代码评测得到:耗时36ms,占用内存14.3MB。

2. 题目二

给出题目二的试题链接如下:

1. 解题思路

这一题没想到啥特别好的方法,就是暴力地求解。

从左往右,从上往下依次遍历,当找到一个非零的元素,就将其视为一个farmland的左上角,然后找到其右上角,并通过其找到对应的右下角即可确定矩形,然后将这个矩形的元素全部进行修改即可避免重复操作。

2. 代码实现

给出python代码实现如下:

class Solution:
    def findFarmland(self, land: List[List[int]]) -> List[List[int]]:
        n, m = len(land), len(land[0])
        res = []
        for i in range(n):
            for j in range(m):
                if land[i][j] != 1:
                    continue
                c = j
                while c < m and land[i][c] == 1:
                    c += 1
                r = i
                while r < n and all(x == 1 for x in land[r][j:c]):
                    r += 1
                res.append([i, j, r-1, c-1])
                for x in range(i, r):
                    for y in range(j, c):
                        land[x][y] = 2
        return res

提交代码评测得到:耗时1172ms,占用内存28MB。

3. 题目三

给出题目三的试题链接如下:

1. 解题思路

这一题感觉也没啥trick可言,就是按照题目意思实现出来就行了……

我们记录下给个节点的父节点,子节点以及其本身的状态,然后upgrade操作当中的父节点与子节点的检查以及更新只需要通过迭代就能够完成了。

2. 代码实现

给出python代码实现如下:

class LockingTree:

    def __init__(self, parent: List[int]):
        self.parent = parent
        self.children = defaultdict(list)
        for i, p in enumerate(parent):
            self.children[p].append(i)
        self.status = [0 for _ in range(len(parent))]
        return

    def lock(self, num: int, user: int) -> bool:
        if self.status[num] == 0:
            self.status[num] = user
            return True
        return False

    def unlock(self, num: int, user: int) -> bool:
        if self.status[num] == user:
            self.status[num] = 0
            return True
        return False

    def upgrade(self, num: int, user: int) -> bool:
        def has_locked_parent(n):
            if n == -1:
                return False
            return self.status[n] != 0 or has_locked_parent(self.parent[n])
        
        def has_locked_children(n):
            if self.children[n] == []:
                return self.status[n] != 0
            return self.status[n] != 0 or any(has_locked_children(k) for k in self.children[n])
        
        def _upgrade(n):
            self.status[n] = 0
            for k in self.children[n]:
                _upgrade(k)
            return
        
        if self.status[num] != 0:
            return False
        elif has_locked_parent(num):
            return False
        elif not has_locked_children(num):
            return False
        self.status[num] = user
        for n in self.children[num]:
            _upgrade(n)
        return True

提交代码评测得到:耗时3486ms,占用内存19.7MB。

4. 题目四

给出题目四的试题链接如下:

1. 解题思路

这一题比想象中简单一些,由于数据只分布在1~30,因此,我们使用一个counter就可能大幅简化数据结构,然后就是考虑数据的选择问题。

显然,1如果存在k个,那么,根据是否包含以及包含多少个1,可以存在 2 k 2^k 2k种选择方式,而对于其他任意一个数,如果这个数可以被某个质数的平方整除,那么这个数无论如何无法被选取;如果这个数x的左右质因子之前都没有被选择过,我么就可以将这个数加入到候选集当中,可选方式有m种,m为数x在整个序列当中存在的次数。

因此,综上,我们就可以快速地通过迭代进行代码实现了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def numberOfGoodSubsets(self, nums: List[int]) -> int:
        MOD = 10**9+7
        
        primes = [2,3,5,7,11,13,17,19,23,29]
        impossible = {4, 8, 12, 16, 20, 24, 28, 9, 18, 27, 25}
        cnt = Counter(nums)
        
        ones = 1
        for i in range(cnt[1]):
            ones = ones * 2 % MOD
        
        status_map = defaultdict(int)
        for i in range(2, 31):
            if i in impossible:
                continue
            status = 0
            for p in primes:
                if i % p == 0:
                    status = (status << 1) + 1
                else:
                    status = status << 1
            status_map[i] = status
        
        @lru_cache(None)
        def dp(k, status):
            if k > 30:
                return 1 if status != 0 else 0
            res = dp(k+1, status)
            if k not in impossible and status_map[k] & status == 0:
                res += cnt[k] * dp(k+1, status ^ status_map[k])
            return res % MOD
        
        return (ones * dp(2, 0)) % MOD  

提交代码评测得到:耗时2677ms,占用内存65.9MB。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值