LeetCode笔记:Weekly Contest 325

  • LeetCode笔记:Weekly Contest 325
    • 1. 题目一
      • 1. 解题思路
      • 2. 代码实现
    • 2. 题目二
      • 1. 解题思路
      • 2. 代码实现
    • 3. 题目三
      • 1. 解题思路
      • 2. 代码实现
    • 4. 题目四
      • 1. 解题思路
      • 2. 代码实现
  • 比赛链接:https://leetcode.com/contest/weekly-contest-325

1. 题目一

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

  • 2515. Shortest Distance to Target String in a Circular Array

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. 题目二

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

  • 2516. Take K of Each Character From Left and Right

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. 题目三

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

  • 2517. Maximum Tastiness of Candy Basket

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. 题目四

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

  • 2518. Number of Great Partitions

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。

你可能感兴趣的:(leetcode笔记,周赛,325,leetcode,2515,leecode,2516,leetcode,2517,leetcode,2518)