LeetCode笔记:Weekly Contest 355

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

1. 题目一

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

  • 2788. Split Strings by Separator

1. 解题思路

这一题还蛮直接的,用python的内置split函数即可进行处理。

2. 代码实现

给出python代码实现如下:

class Solution:
    def splitWordsBySeparator(self, words: List[str], separator: str) -> List[str]:
        res = []
        for w in words:
            res.extend([token for token in w.split(separator) if token != ""])
        return res

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

2. 题目二

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

  • 2789. Largest Element in an Array after Merge Operations

1. 解题思路

这一题的思路上其实也挺直接的,相当于就是一个倒序的有序数组,从后往前,如果满足合并条件,就将数字进行合并,直到无法合并时,就更新下一个需要操作的数字。

由此,我们就能够得到最终的一系列数字,然后我们返回最大值即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maxArrayValue(self, nums: List[int]) -> int:
        res = 0
        n = len(nums)
        prev = nums[-1]
        for i in range(n-2, -1, -1):
            if nums[i] <= prev:
                prev += nums[i]
            else:
                res = max(res, prev)
                prev = nums[i]
        res = max(res, prev)
        return res

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

3. 题目三

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

  • 2790. Maximum Number of Groups With Increasing Length

1. 解题思路

这一题思路上来说我用的是二分法,就是通过二分的方式找到最大的可以找到构造方式的group数目即可。

从而,问题就变成了,给出group数目 k k k,如何判断能否成功分割。

我们选择usageLimits最大的 k k k个数字进行基底,然后考察能否进行分配。此时,剩余的数字的usageLimits就可以全部用来做冗余数进行填补。

然后,我们从usageLimits排序小到大进行考察,分别从大到小填充各个group,比如说,第 i i i大的值就填充 i i i个group,然后多余的就可以全部添加到冗余当中,由于本身usageLimits是从小到大排列的,因此不可能出现被视为冗余的元素被重复填充到了同一个group当中,因为后者的元素个数一定被前者多,所以前者能够被填充到某一个group那么后者一定也能够被填充到某一个group当中。

由此,我们只需要判断是否可以完成填充即可,如果某一次无法成功填充,那么就一定无法成功分配,反之即可成功分配到 k k k个group当中。

2. 代码实现

给出python代码实现如下:

class Solution:
    def maxIncreasingGroups(self, usageLimits: List[int]) -> int:
        n = len(usageLimits)
        usageLimits = sorted(usageLimits, reverse=True)
        accums = [0] + list(accumulate(usageLimits))
        
        def can_split(k):
            remain = accums[-1] - accums[k]
            for i in range(k):
                need = i+1
                idx = k-1-i
                if need > usageLimits[idx] + remain:
                    return False
                if usageLimits[idx] > need:
                    remain += min(k-need, usageLimits[idx] - need)
                else:
                    remain -= need - usageLimits[idx]
            return True
        
        i, j = 1, n+1
        while j-i>1:
            k = (i+j) // 2
            if can_split(k):
                i = k
            else:
                j = k
        return i

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

4. 题目四

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

  • 2791. Count Paths That Can Form a Palindrome in a Tree

1. 解题思路

这一题思路上来说个人还是觉得有点巧妙的。

具体来说,我们可以通过一个遍历给出每一个点从根节点到他们的路径,这个是不难实现的。然后,我们就可以将每一个点用他们的路径来进行表达。

此时,如果存在某两个点 u , v u, v u,v,他们之间的路径可以构成一个回文,那么显然从根节点到这两个点的路径的concat必然也能够构成一个回文,因为他们之间如果存在有重复的路径,那么这条路径一定被走了两遍,对回文的构造不会产生任何影响。

基于这个思路,我们就可以对这个问题进行解答。

显然,要构成回文字符串,那么当且仅当两条路径合在一起时最多只有一个字符的个数为奇数,因此,事实上我们只需要考察每一个点所代表的路径当中26个字母的奇偶性即可,因此,我们事实上可以只考虑奇偶性用一个26位的数字来替换掉完整的路径,此时我们便可以优化回文的判断。

此时,对于任何一个节点,其对应的路径假设为 v v v,我们只需要考察:

  1. 同样路径为 v v v的点,此时共有 C n 2 C_n^2 Cn2种组合;
  2. 路径为 u u u的点,满足 u , v u, v u,v仅存在一位不同,此时能够形成的组合数就是 n u × n v n_u \times n_v nu×nv

当然,考虑到路径的唯一性,我们事实上还需要进行去重处理,不过也不是什么大事就是了。

2. 代码实现

给出python代码实现如下:

class Solution:
    def countPalindromePaths(self, parent: List[int], s: str) -> int:
        children = defaultdict(list)
        for i, p in enumerate(parent):
            children[p].append(i)
            
        cnt = defaultdict(int)
        q = [(0, 0)]
        while q != []:
            p, v = q.pop(0)
            cnt[v] += 1
            for c in children[p]:
                r = s[c]
                q.append((c, v ^ (1 << (ord(r) - ord('a')))))
        
        res = 0
        keys = list(cnt.keys())
        for k in keys:
            v = cnt[k]
            res += v * (v-1)
            for i in range(26):
                res += v * cnt[k ^ (1 << i)]
        return res // 2

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

你可能感兴趣的:(leetcode笔记,力扣周赛,355,leetcode,2788,leetcode,2789,leetcode,2790,leetcode,2791)