LeetCode笔记:Biweekly Contest 94

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

1. 题目一

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

  • 2511. Maximum Enemy Forts That Can Be Captured

1. 解题思路

这一题事实上有一点无聊,因为全部的难度事实上都只在读题目上而已,其实核心点就两点:

  1. 必须从一个1的节点开始,停到一个-1的节点上;
  2. 路径当中的所有的节点除了首位之外值均为0;

在这种情况下,令路径长度最大化。

因此,我们只需要正反两向各自遍历一下即可。

2. 代码实现

给出python代码实现如下:

class Solution:
    def captureForts(self, forts: List[int]) -> int:
        res = 0
        
        cnt = 0
        have_army = False
        for i in forts:
            if not have_army:
                if i == 1:
                    have_army = True
            else:
                if i == 1:
                    cnt = 0
                elif i == 0:
                    cnt += 1
                else:
                    res = max(res, cnt)
                    cnt = 0
                    have_army = False

        cnt = 0
        have_army = False
        for i in forts[::-1]:
            if not have_army:
                if i == 1:
                    have_army = True
            else:
                if i == 1:
                    cnt = 0
                elif i == 0:
                    cnt += 1
                else:
                    res = max(res, cnt)
                    cnt = 0
                    have_army = False
        return res

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

2. 题目二

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

  • 2512. Reward Top K Students

1. 解题思路

这一题其实就是根据每个学生的report计算一下学生的评价分数,然后排个序取前k个即可。

于是剩下的问题就是如何相对高效的求一下学生们的分数了,而这个其实只需要对positive和negative的词汇做一个hash表就可以相对快速地进行判断了,也不是啥难事。

2. 代码实现

给出python代码实现如下:

class Solution:
    def topStudents(self, positive_feedback: List[str], negative_feedback: List[str], report: List[str], student_id: List[int], k: int) -> List[int]:
        positive_feedback, negative_feedback = set(positive_feedback), set(negative_feedback)
        n = len(student_id)
        
        def get_score(report):
            score = 0
            for w in report.split():
                if w in positive_feedback:
                    score += 3
                elif w in negative_feedback:
                    score -= 1
            return score
        
        score = [(get_score(report[i]), -student_id[i]) for i in range(n)]
        score = sorted(score, reverse=True)[:k]
        return [-x[1] for x in score]

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

3. 题目三

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

  • 2513. Minimize the Maximum of Two Arrays

1. 解题思路

这一题其实非常的简单,就是用二分法找到第一个可以满足的n,使得不小于n的数可以分成两个不重叠的array使得:

  1. 第一个array包含至少uniqueCnt1个数,且其中的数都不被divisor1整除;
  2. 第二个array包含至少uniqueCnt2个数,且其中的数都不被divisor2整除。

而要考察这个n能否成立,我们其实还是相当简单可以通过下述方式快速判断的:

  1. 不小于n的数当中,仅不能被divisor1整除全部归于array1;
  2. 不小于n的数当中,仅不能被divisor2整除全部归于array2;
  3. 同时不被divisor1与divisor2整除的数个数大于剩余的坑位即可完成构造。

因此,剩下的问题就是如何求出剩下几个值:

  1. 不小于n的数当中,仅不能被divisor1整除的数;
  2. 不小于n的数当中,仅不能被divisor2整除的数;
  3. 不小于n的数当中,同时不被divisor1与divisor2整除的数;

而这个其实通过容斥原理其实还是非常容易化简为求下列三个数:

  1. 不小于n的数当中,能被divisor1整除的数,记为s1;
  2. 不小于n的数当中,能被divisor2整除的数,记为s2;
  3. 不小于n的数当中,同时能被divisor1与divisor2整除的数,即为s3;

则:

  1. 同时不被divisor1与divisor2整除的数为:t3 = (n-s1) + (n-s2) + s3 - n
  2. 仅不能被divisor1整除的数:t1 = n - s1 - t3
  3. 仅不能被divisor2整除的数:t2 = n - s2 - t3

由此,问题即可求解。

2. 代码实现

给出python代码实现如下:

class Solution:
    def minimizeSet(self, divisor1: int, divisor2: int, uniqueCnt1: int, uniqueCnt2: int) -> int:
        _lcm = lcm(divisor1, divisor2)
        # print(_lcm)
        def is_possible(n):
            cnt1 = n - n // divisor1
            cnt2 = n - n // divisor2
            cnt3 = cnt1 + cnt2 + n // _lcm - n
            return max(uniqueCnt1 - (cnt1 - cnt3), 0) + max(uniqueCnt2 - (cnt2 - cnt3), 0) <= cnt3
        
        i, j = 0, 10**10
        while j-i > 1:
            n = (i+j)//2
            if is_possible(n):
                j = n
            else:
                i = n
        return j

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

4. 题目四

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

  • 2514. Count Anagrams

1. 解题思路

这一题思路上来说同样也比较直接,就是求取一下每一个单词的同构数目然后相乘求余即可。

而如何求取每一个单词的同构数目,其实也是一个非常简单的排列组合的题目,假设单词总长为n,包含了m个字符,每个字符的个数为 n m n_m nm,则单词的同构数目即为:

s = n ! Π i = 1 m n i ! s = \frac{n!}{\mathop{\Pi}\limits_{i=1}^{m}n_i!} s=i=1Πmni!n!

由此,问题得解。

2. 代码实现

给出python代码实现如下:

class Solution:
    def countAnagrams(self, s: str) -> int:
        MOD = 10**9+7
        
        @lru_cache(None)
        def count_anagram(w):
            n = len(w)
            ms = Counter(w).values()
            res = math.factorial(n)
            for m in ms:
                res = res * pow(math.factorial(m), -1, mod=MOD) % MOD
            return res
            
        res = 1
        for w in s.split():
            res = res * count_anagram(w) % MOD
        return res

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

你可能感兴趣的:(leetcode笔记,双周赛,94,leetcode,2511,leetcode,2512,leetcode,2513,leetcode,2514)