LeetCode笔记:Weekly Contest 325

1. 题目一

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

1. 解题思路

这一题的思路还是很直接的,就是找一下每一个target的单词与startIndex之间的正反距离然后取最小值即可。

如果target不存在,则返回-1。

2. 代码实现

给出python代码实现如下:

class Solution:
    def closetTarget(self, words: List[str], target: str, startIndex: int) -> int:
        n = len(words)
        res = n+1
        for i, w in enumerate(words):
            if w == target:
                res = min(res, (startIndex - i + n) % n, (i - startIndex + n) % n)
        return res if res != n+1 else -1

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

2. 题目二

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

1. 解题思路

这一题思路上就是一个滑动窗口。

我们首先只看左侧,只取左边的元素然后令所有元素个数均不少于k。

然后,我们考虑左侧元素每减少一个,需要从右侧补充多少个元素进行补偿,维护这个滑动窗口直至左侧元素清零。

此时,我们返回所有情况下的最小值即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def takeCharacters(self, s: str, k: int) -> int:
        cnt = defaultdict(int)
        n = len(s)
        i, j = 0, n-1
        while i < n:
            cnt[s[i]] += 1
            i += 1
            if all(cnt[ch] >= k for ch in "abc"):
                break
        if any(cnt[ch] < k for ch in "abc"):
            return -1
        res = i
        while i > 0:
            i -= 1
            cnt[s[i]] -= 1
            while any(cnt[ch] < k for ch in "abc"):
                cnt[s[j]] += 1
                j -= 1
            res = min(res, i + n-1 - j)
        return res

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

3. 题目三

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

1. 解题思路

这一题思路上就是一个二分法。

我们假设candy之间的价格差距不少于d,然后通过二分法看一下在这种情况下能否构造一个bucket使得其中的candy总数不少于k。然后我们通过二分法找出d可取的最大值即可。

而关于在价格差距为d的情况下能否构造的问题,我们可以先将price进行排序,然后用二分查找的方式依次找到在间隔不少于d的情况下的下一种糖果的价格,然后看看能否取到k种糖果即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maximumTastiness(self, price: List[int], k: int) -> int:
        price = sorted(price)
        n = len(price)
        
        def is_possible(d):
            idx = 0
            for _ in range(k):
                if idx >= n:
                    return False
                idx = bisect.bisect_left(price, price[idx] + d, lo=idx)
            return True
        
        i, j = 0, (price[-1] - price[0]) // (k-1) + 1
        while j-i > 1:
            d = (j+i) // 2
            if is_possible(d):
                i = d
            else:
                j = d
        return i

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

4. 题目四

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

1. 解题思路

这一题思路上我其实还是非常暴力的就用了一个动态规划 + 剪枝的方法,也算是面对超时编程了。

动态规划的方法其实很简单了,就不多做展开了,这里就具体讲讲要如何剪枝:

  1. 我们记录下两个组合中的已有元素之和,如果两边的和都已经大于目标值k,那么剩下的元素(不妨设为m个)就可以直接随机分到两个组合当中了,即 2 m 2^m 2m种组合;
  2. 我们对原数组从大到小排个序,优先对大的元素进行分组,这样可以更快速地达到1当中的条件,进而更进一步地实现剪枝。

通过上述两个操作,虽然方法依然不怎么优雅,不过还是可以通过全部的测试样例,甚至耗时还算过得去……

2. 代码实现

给出python代码实现如下:

class Solution:
    def countPartitions(self, nums: List[int], k: int) -> int:
        nums = sorted(nums, reverse=True)
        
        MOD = 10**9 + 7
        s = sum(nums)
        n = len(nums)
        
        @lru_cache(None)
        def dp(idx, s1, s2):
            if s1 >= k and s2 >= k:
                return pow(2, n-idx, MOD)
            elif s1 > s-k or s2 > s-k or idx >= n:
                return 0
            return (dp(idx+1, s1 + nums[idx], s2) + dp(idx+1, s1, s2 + nums[idx])) % MOD
        
        return dp(0, 0, 0)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值