【LeetCode周赛】第194场周赛

一、1486. 数组异或操作:

给你两个整数,n 和 start 。

数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。

请返回 nums 中所有元素按位异或(XOR)后得到的结果。

示例:

输入:n = 5, start = 0
输出:8
解释:数组 nums 为 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。
"^" 为按位异或 XOR 运算符。

分析:

​ 简单的模拟过程。

代码(Python):

class Solution:
    def xorOperation(self, n: int, start: int) -> int:
        ans = 0
        for i in range(n):
            cur = start + 2 * i
            ans = ans ^ cur
        return ans

二、1487. 保证文件名唯一

给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹:在第 i 分钟,新建名为 names[i] 的文件夹。

由于两个文件 不能 共享相同的文件名,因此如果新建文件夹使用的文件名已经被占用,系统会以(k) 的形式为新文件夹的文件名添加后缀,其中 k 是能保证文件名唯一的 最小正整数

返回长度为 n 的字符串数组,其中 ans[i] 是创建第 i 个文件夹时系统分配给该文件夹的实际名称。

示例:

输入:names = ["pes","fifa","gta","pes(2019)"]
输出:["pes","fifa","gta","pes(2019)"]
解释:文件系统将会这样创建文件名:
"pes" --> 之前未分配,仍为 "pes"
"fifa" --> 之前未分配,仍为 "fifa"
"gta" --> 之前未分配,仍为 "gta"
"pes(2019)" --> 之前未分配,仍为 "pes(2019)"

输入:names = ["kaido","kaido(1)","kaido","kaido(1)"]
输出:["kaido","kaido(1)","kaido(2)","kaido(1)(1)"]
解释:注意,如果含后缀文件名被占用,那么系统也会按规则在名称后添加新的后缀 (k) 。

分析:

​ 当时在做的时候写了几个版本:

​ (1):题目理解错误。我直接把所有文件名后面的括号及括号中数字全部去掉。接着利用哈希表存储同名元素个数。但是示例二提示:含后缀文件名被占用,那么还要继续添加新后缀。

​ (2):TLE。理解正确,但是

# ...
name_set = defaultdict(int)
for name in names:
    # 如果第一次出现该文件名
    if not name_set[name]:
        ans.append(name)
        name_set[name] += 1
    # 如果已经出现,最重要的部分!
    else:
        times = 0
        new_name = "{name}({times})".format(name=name, times=times)
        while name_set[new_name]:
            times += 1
            new_name = "{name}({times})".format(name=name, times=times)
        ans.append(new_name)
        name_set[new_name] += 1
# ...
  • 当发现该文件名已经被占用,首先添加后缀,如果后缀仍然被占用,则括号中数字不断++。
  • 上面就是题目的大概思路,但是问题在于没有利用Hash表中存储的数字。对上面的代码稍加修改就可以通过。

代码(Python):

class Solution:
    def getFolderNames(self, names: List[str]) -> List[str]:
        ans = []
        name_set = defaultdict(int)
        for name in names:
            if not name_set[name]:
                ans.append(name)
                name_set[name] += 1
            else:
                # 非常重要,由于defaultdict(int)默认值为0,而此时直接插入已经失败,说明要添加后缀
                # 如果此时的name已经带后缀,应该直接加后缀,下标应从1开始
                if not name_set[name]:
                    name_set[name] = 1

                new_name = "{name}({times})".format(name=name, times=name_set[name])
                while name_set[new_name]:
                    name_set[name] += 1
                    new_name = "{name}({times})".format(name=name, times=name_set[name])
                ans.append(new_name)
                name_set[new_name] += 1
        return ans

三、1488. 避免洪水泛滥

你的国家有无数个湖泊,所有湖泊一开始都是空的。当第 n 个湖泊下雨的时候,如果第 n 个湖泊是空的,那么它就会装满水,否则这个湖泊会发生洪水。你的目标是避免任意一个湖泊发生洪水。

给你一个整数数组 rains ,其中:

  • rains[i] > 0 表示第 i 天时,第 rains[i] 个湖泊会下雨。

  • rains[i] == 0 表示第 i 天没有湖泊会下雨,你可以选择 一个 湖泊并 抽干 这个湖泊的水。

请返回一个数组 ans ,满足:

  • ans.length == rains.length

  • 如果 rains[i] > 0 ,那么ans[i] == -1

  • 如果 rains[i] == 0 ,ans[i] 是你第 i 天选择抽干的湖泊。

如果有多种可行解,请返回它们中的 任意一个 。如果没办法阻止洪水,请返回一个 空的数组

请注意,如果你选择抽干一个装满水的湖泊,它会变成一个空的湖泊。但如果你选择抽干一个空的湖泊,那么将无事发生(详情请看示例 4)。

示例:

输入:rains = [1,2,3,4]
输出:[-1,-1,-1,-1]
解释:第一天后,装满水的湖泊包括 [1]
第二天后,装满水的湖泊包括 [1,2]
第三天后,装满水的湖泊包括 [1,2,3]
第四天后,装满水的湖泊包括 [1,2,3,4]
没有哪一天你可以抽干任何湖泊的水,也没有湖泊会发生洪水。

输入:rains = [1,2,0,0,2,1]
输出:[-1,-1,2,1,-1,-1]
解释:第一天后,装满水的湖泊包括 [1]
第二天后,装满水的湖泊包括 [1,2]
第三天后,我们抽干湖泊 2 。所以剩下装满水的湖泊包括 [1]
第四天后,我们抽干湖泊 1 。所以暂时没有装满水的湖泊了。
第五天后,装满水的湖泊包括 [2]。
第六天后,装满水的湖泊包括 [1,2]。
可以看出,这个方案下不会有洪水发生。同时, [-1,-1,1,2,-1,-1] 也是另一个可行的没有洪水的方案。

输入:rains = [1,2,0,1,2]
输出:[]
解释:第二天后,装满水的湖泊包括 [1,2]。我们可以在第三天抽干一个湖泊的水。
但第三天后,湖泊 1 和 2 都会再次下雨,所以不管我们第三天抽干哪个湖泊的水,另一个湖泊都会发生洪水。

分析:

​ 双端队列 + 哈希表。具体代码看了一个大佬的题解,我又补充了一些注释。注释分析的已经很不错了,之后再补充一些分析和总结。

代码(Python):

class Solution:
    def avoidFlood(self, rains: List[int]) -> list[int]:
        # 使用deque可以确保日期小的在前面
        lake_to_days = defaultdict(deque)
        for date, lake in enumerate(rains):
            if lake != 0:
                lake_to_days[lake].append(date)
        q = []
        full = set()
        res = []
        for date, lake in enumerate(rains):
            if lake != 0:
                # 当前湖已经满了,无法避免洪水
                if lake in full: 
                    return []
                else:
                    # 依题意,如果该天下雨,不可以抽水
                    res.append(-1)
                    # 将当前湖加入full
                    full.add(lake)
                    # 左侧的第一个日期就是该日期,所以删除
                    lake_to_days[lake].popleft()
                    # 如果该湖之后还要下雨,将日期加入优先队列中
                    if lake_to_days[lake]:
                        hq.heappush(q, lake_to_days[lake][0])
            else:
                # 优先队列为空,且根据题目要求rains[i] == 0,需排水,因此随便抽一个湖即可
                if not q:
                    res.append(1)
                # 选取优先队列中最小的日期,将在该日期下雨的湖抽干
                else:
                    date = hq.heappop(q)
                    res.append(rains[date])
                    full.remove(rains[date])
        return res

原文地址:https://www.cnblogs.com/enmac/p/13197582.html