Manjusaka

Manjusaka

Leetcode 每週競賽 287 題解

好久沒打周賽了,打了一次周賽,簡單的寫個題解

2224. 轉換時間的最小操作次數#

題面:

你給定了兩個字符串 current 和 correct,表示兩個 24 小時制的時間。

24 小時制的時間格式為 "HH:MM",其中 HH 在 00 到 23 之間,MM 在 00 到 59 之間。最早的 24 小時制時間是 00:00,最晚的是 23:59。

在一次操作中,你可以將時間 current 增加 1、5、15 或 60 分鐘。你可以進行任意次數的操作。

返回將 current 轉換為 correct 所需的最小操作次數。

示例:

 

示例 1:

輸入:current = "02:30",correct = "04:35"
輸出:3
解釋:
我們可以通過以下 3 次操作將 current 轉換為 correct:
- 將 current 增加 60 分鐘。current 變為 "03:30"。
- 將 current 增加 60 分鐘。current 變為 "04:30"。
- 將 current 增加 5 分鐘。current 變為 "04:35"。
可以證明,無法在少於 3 次操作中將 current 轉換為 correct。

示例 2:

輸入:current = "11:00",correct = "11:01"
輸出:1
解釋:我們只需將 current 增加一分鐘,因此所需的最小操作次數為 1。

這題沒啥好說的吧,直接暴力計算時間寫就行

class Solution:
    def convertTime(self, current: str, correct: str) -> int:
        correct_time = correct.split(':')
        current_time = current.split(':')
        minutes = int(correct_time[1]) - int(current_time[1])
        hours = int(correct_time[0]) - int(current_time[0])
        if correct_time[1] < current_time[1]:
            minutes += 60
            hours -= 1
        results = hours
        flag = [15, 5, 1]
        for i in flag:
            if minutes >= i:
                results += (minutes // i)
                minutes = minutes % i
        return results

2225. 找到零或一場失利的玩家#

題面:

你給定了一個整數數組 matches,其中 matches[i] = [winneri, loseri] 表示玩家 winneri 在比賽中擊敗了玩家 loseri。

返回一個大小為 2 的列表 answer,其中:

answer[0] 是所有未輸過比賽的玩家列表。
answer[1] 是所有僅輸過一場比賽的玩家列表。
兩個列表中的值應按增序返回。

注意:

你應該只考慮至少參加過一場比賽的玩家。
測試用例將生成這樣的情況,即沒有兩場比賽會有相同的結果。

示例:

示例 1:

輸入:matches = [[1,3],[2,3],[3,6],[5,6],[5,7],[4,5],[4,8],[4,9],[10,4],[10,9]]
輸出:[[1,2,10],[4,5,7,8]]
解釋:
玩家 1、2 和 10 沒有輸過比賽。
玩家 4、5、7 和 8 各輸過一場比賽。
玩家 3、6 和 9 各輸過兩場比賽。
因此,answer[0] = [1,2,10] 和 answer[1] = [4,5,7,8]。


示例 2:

輸入:matches = [[2,3],[1,3],[5,4],[6,4]]
輸出:[[1,2,5,6],[]]
解釋:
玩家 1、2、5 和 6 沒有輸過比賽。
玩家 3 和 4 各輸過兩場比賽。
因此,answer[0] = [1,2,5,6] 和 answer[1] = []。

這題實際上就遍歷統計就行,時間複雜度 O (N) 空間複雜度 O (N)

from collections import defaultdict
from typing import List


class Solution:
    def findWinners(self, matches: List[List[int]]) -> List[List[int]]:
        index = defaultdict(lambda: [0, 0])
        for winner, loser in matches:
            index[winner][0] += 1
            index[loser][1] += 1
        return [
            sorted([k for k, v in index.items() if v[0] > 0 and v[1] == 0]),
            sorted([k for k, v in index.items() if v[1] == 1]),
        ]

2226. 分配給 K 個孩子的最大糖果數量#

草,這題題號真有意思,尊。。。。

題面:


你給定了一個 0 索引的整數數組 candies。數組中的每個元素表示大小為 candies[i] 的糖果堆。你可以將每堆糖果分成任意數量的子堆,但不能將兩堆糖果合併在一起。

你還給定了一個整數 k。你應該將糖果堆分配給 k 個孩子,使得每個孩子獲得相同數量的糖果。每個孩子最多可以拿一堆糖果,並且某些糖果堆可能不會被使用。

返回每個孩子可以獲得的最大糖果數量。

示例:

示例 1:

輸入:candies = [5,8,6],k = 3
輸出:5
解釋:我們可以將 candies[1] 分成大小為 5 和 3 的 2 堆,將 candies[2] 分成大小為 5 和 1 的 2 堆。我們現在有五堆糖果,大小為 5、5、3、5 和 1。我們可以將 3 堆大小為 5 的糖果分配給 3 個孩子。可以證明,每個孩子不能獲得超過 5 顆糖果。

示例 2:

輸入:candies = [2,5],k = 11
輸出:0
解釋:有 11 個孩子,但總共只有 7 顆糖果,因此無法確保每個孩子至少獲得一顆糖果。因此,每個孩子都得不到糖果,答案是 0。

這題實際上最開始沒想清楚,後面仔細想了下,實際上是個二分的題目

首先假設,我們所有的糖的和為 y,假設被 k 整除後的值是 z(含義是最大的能夠整數分割的數),那麼我們題目裡孩子能獲得的最大的糖果的數量的值域一定是 [0,z]

這個區間是具備單調性(單調遞增),那麼就具備了二分的條件。那麼我們二分的題目是什麼?假設中間值是 mid,我們計算每推糖果能夠按照 mid 分成幾份並求和,如果和小於 k,那麼意味著值比我們目標值大,否則則比目標值小。持續逼近即可

from typing import List


class Solution:
    def maximumCandies(self, candies: List[int], k: int) -> int:
        left, right = 0, sum(candies) // k
        while left < right:
            mid = (left + right + 1) // 2
            if k > sum(candy // mid for candy in candies):
                right = mid - 1
            else:
                left = mid
        return left

2227. 加密和解密字符串#

這題實際上比第三題簡單

題面:

你給定了一個字符數組 keys,包含唯一字符,還有一個字符串數組 values,包含長度為 2 的字符串。你還給定了另一個字符串數組 dictionary,包含所有經過解密的原始字符串。你應該實現一個數據結構,可以加密或解密一個 0 索引的字符串。

字符串的加密過程如下:

對於字符串中的每個字符 c,我們找到滿足 keys[i] == c 的索引 i。
用 values[i] 替換字符串中的 c。
字符串的解密過程如下:

對於字符串中出現在偶數索引的每個長度為 2 的子字符串 s,我們找到一個 i,使得 values[i] == s。如果有多個有效的 i,我們可以選擇其中任何一個。這意味著一個字符串可能有多個可能的字符串可以解密。
用 keys[i] 替換字符串中的 s。
實現 Encrypter 類:

Encrypter(char[] keys, String[] values, String[] dictionary) 初始化 Encrypter 類,使用 keys、values 和 dictionary。
String encrypt(String word1) 使用上述加密過程加密 word1 並返回加密字符串。
int decrypt(String word2) 返回 word2 可能解密為的字符串數量,這些字符串也出現在字典中。

示例:

輸入
["Encrypter", "encrypt", "decrypt"]
[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]
輸出
[null, "eizfeiam", 2]

解釋
Encrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);
encrypter.encrypt("abcd"); // 返回 "eizfeiam"。 
                           // 'a' 對應 "ei",'b' 對應 "zf",'c' 對應 "ei",'d' 對應 "am"。
encrypter.decrypt("eizfeiam"); // 返回 2。 
                              // "ei" 可以對應 'a' 或 'c',"zf" 對應 'b',"am" 對應 'd'。 
                              // 因此,解密後的可能字符串為 "abad"、"cbad"、"abcd" 和 "cbcd"。 
                              // 其中 2 個字符串 "abad" 和 "abcd" 出現在字典中,因此答案是 2。

這題加密部分其實直接按照規則寫就行了,然後解密部分有個方法就是提前將字典裡面的值預計算一次,然後就能 O (1) 計算了

from collections import Counter
from typing import List


class Encrypter:
    def __init__(self, keys: List[str], values: List[str], dictionary: List[str]):
        self.index = {k: v for k, v in zip(keys, values)}
        self.counter = Counter(self.encrypt(item) for item in dictionary)

    def encrypt(self, word1: str) -> str:
        return "".join(self.index.get(letter, " ") for letter in word1)

    def decrypt(self, word2: str) -> int:
        return self.counter[word2]

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。