「LeetCode」第 66 场双周赛(上)

133 阅读3分钟

这是我参与11月更文挑战的第15天,活动详情查看2021最后一次更文挑战

链接

leetcode-cn.com/contest/biw…

题目

2085. 统计出现过一次的公共字符串

哈希表

解析

最简单的哈希表思路是用两个哈希表分别统计出现过的字母,然后遍历某个哈希表中出现过的字母判断是否都为1即可。
用LeetCode PlayGround中Python自带的collection.Counter方法可以直接获得统计结果的字典

代码

class Solution:
    def countWords(self, words1: List[str], words2: List[str]) -> int:
        freq1 = Counter(words1)   # words1 中字符串的出现次数
        freq2 = Counter(words2)   # words2 中字符串的出现次数
        res = 0   # 出现过一次的公共字符串个数
        for word1 in freq1.keys():
            # 遍历 words1 出现的字符并判断是否满足要求
            if freq1[word1] == 1 and freq2[word1] == 1:
                res += 1
        return res

另一种做法是只用一个字典统计,但是要多加很多判断。

class Solution:
    def countWords(self, words1: List[str], words2: List[str]) -> int:
        validDict = defaultdict(int)
        for word in words1:
            validDict[word] += 1
        ans = 0
        for word in words2:
            if not word in validDict:
                continue
            if validDict[word] == 1:
                ans += 1
                validDict[word] = 0
            elif validDict[word] == 0:
                ans -= 1
                validDict[word] = 2
        return ans

2086. 从房屋收集雨水需要的最少水桶数

贪心

解析

最简单的做法是以贪心思想一次遍历数组中的所以房屋位置,只需要两个额外变量:上一个桶位置和桶总计数即可。在每遍历到一个新房屋时,先判断其左边是否是上一个桶、若不是则是否可以在其右边放下下一个桶、若不是则是否可以在左边放下下一个桶,都不行的话即返回-1。

代码

class Solution:
    def minimumBuckets(self, street: str) -> int:
        lastInd, ans = -2, 0
        for i, house in enumerate(street):
            if house == '.':
                continue
            elif lastInd == i-1:
                continue
            elif i+1 < len(street) and street[i+1] == '.':
                ans += 1
                lastInd = i+1
            elif i-1 >= 0 and street[i-1] == '.':
                ans += 1
                lastInd = i-1
            else:
                return -1
        return ans

另一种贪心

解析

另一种贪心的思路是“只判断右边的情况”,即如果在某个位置放置桶的话,跳到这个位置的右边两个位置。
这里有两种实现思路:对每个遍历到的房屋进行逻辑判断和对每个遍历到可放置桶位置进行逻辑判断。

代码

对房屋进行判断

class Solution:
    def minimumBuckets(self, street: str) -> int:
        n = len(street)
        i = ans = 0
        while i < n:
            if street[i] == "H":
                if i + 1 < n and street[i + 1] == ".":
                    ans += 1
                    # 直接跳过后续的两个位置
                    i += 2
                elif i - 1 >= 0 and street[i - 1] == ".":
                    ans += 1
                else:
                    return -1
            i += 1
        return ans

对可放置桶位置进行判断

class Solution:
    def minimumBuckets(self, street: str) -> int:
        n = len(street)
        if n == 1:
            if street[0] == '.':
                return 0
            else:
                return -1
        elif n == 2:
            if street[0] == street[1] == 'H':
                return -1
            elif street[0] == street[1] == '.':
                return 0
            else:
                return 1
        p = 0
        ans = 0
        while p < n-2:
            if street[p] == 'H':
                if street[p+1] == 'H':
                    if p == 0 or street[p-1] == 'H':
                        return -1
                    else:
                        ans += 1
                        p += 1
                else:
                    ans += 1
                    p += 3
            else:
                p += 1
        if p == n-1:
            if street[p] == 'H':
                if street[p-1] == 'H':
                    return -1
                else:
                    ans += 1
        elif p == n-2:
            if street[p] == 'H' and street[p+1] == 'H':
                return -1
            elif street[p] == 'H' and street[p+1] == '.':
                ans += 1
            elif street[p] == '.' and street[p+1] == 'H':
                ans += 1
        return ans