Manjusaka

Manjusaka

Leetcode 雙週賽 19 題解

例行 Leetcode 周賽,這周雙周賽,兩場賽打下來,有點酸爽,先寫個 BiWeekly 19 Contest 的題解吧

1342. 將一個數字減至零的步數#

題面:

給定一個非負整數 num,返回將其減至零的步數。如果當前數字是偶數,則必須將其除以 2,否則,必須從中減去 1。

示例:

Input: num = 14
Output: 6
Explanation:
    Step 1) 14 是偶數;除以 2 得到 7。 
    Step 2) 7 是奇數;減去 1 得到 6。
    Step 3) 6 是偶數;除以 2 得到 3。 
    Step 4) 3 是奇數;減去 1 得到 2。 
    Step 5) 2 是偶數;除以 2 得到 1。 
    Step 6) 1 是奇數;減去 1 得到 0。

這個題題面很簡單,一個非負整數,偶數除 2,奇數減 1,求需要多少步到 0

暴力寫

class Solution:
    def numberOfSteps(self, num: int) -> int:
        count = 0
        if num == 0:
            return count
        result = num
        while result > 1:
            if result % 2 == 0:
                result = int(result / 2)
            else:
                result -= 1
            count += 1
        return count + 1

大小為 K 且平均數大於或等於閾值的子數組的數量#

題面:

給定一個整數數組 arr 和兩個整數 k 和 threshold。
返回大小為 k 且平均數大於或等於閾值的子數組的數量。

示例:

Input: arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4
Output: 3
Explanation: 子數組 [2,5,5],[5,5,5] 和 [5,5,8] 的平均數分別為 4, 5 和 6。所有其他大小為 3 的子數組的平均數均小於 4(閾值)

給定一個數組和一個長度 k,和一個閾值 threshold ,求這個數組中的所有長度為 K 且平均數大於等於閾值的子數組的個數。這個題,暴力寫很簡單,一個簡單的數組的拆分,sum(arr[i:i+k])/k >= threshold 即可,但是這裡有個問題,如果實時求和,那麼時間複雜度為 O (M*K) M 為數組的長度,這個時候暴力會 T

因此需要做個小技巧的優化。可以考慮這樣這樣一個做法,假設當前 i 及其後 k 個數的和為 sum [i],那麼有這樣一個公式,sum [i]=sum [i-1]-arr [i]+arr [i+k-1],這樣每次計算和都是 O (1) 的複雜度,那麼整體就是一個 O (N) 的做法

好了,暴力開寫

from typing import List


class Solution:
    def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
        if not arr:
            return 0
        length = len(arr)
        sum_threshold = [0.0] * length
        count = 0
        last_index = length
        for i in range(length - k, -1, -1):
            if i == length - k:
                total_sum = sum(arr[i:i + k])
            else:
                total_sum = sum_threshold[i + 1] - arr[last_index] + arr[i]
            sum_threshold[i] = total_sum

            if total_sum / k >= threshold:
                count += 1
            last_index -= 1
        return count

1344. 鐘表指針之間的角度#

題面:

給定兩個數字,hour 和 minutes。返回時針和分針之間形成的較小角度(以度為單位)。

示例:

image

Input: hour = 12, minutes = 30
Output: 165

求某個時刻,時針與分針的夾角,,,啊,,我的上帝呀,一度夢回小升初。。。一個數學題,首先科普如下知識

  1. 普通鐘表相當於圓,其時針或分針走一圈均相當於走過 360° 角;

  2. 鐘表上的每一個大格(時針的一小時或分針的 5 分鐘)對應的角度是:360°/12=30°;

  3. 時針每走過 1 分鐘對應的角度應為:360°/(12*60)=0.5°;

  4. 分針每走過 1 分鐘對應的角度應為:360°/60=6°。

好了,那麼就暴力做吧

class Solution:
    def angleClock(self, hour: int, minutes: int) -> float:
        hour %= 12
        result = abs((minutes * 6) - (hour * 30 + minutes * 0.5))
        return result if result < 360 else 360 - result

1345. 跳躍遊戲 IV#

題面:

給定一個整數數組 arr,你最初位於數組的第一個索引。
在一步中,你可以從索引 i 跳到索引:

  1. i + 1 其中:i + 1 < arr.length。
  2. i - 1 其中:i - 1 >= 0。
  3. j 其中:arr [i] == arr [j] 且 i != j。
    返回到達數組最後一個索引的最小步數。
    注意,你不能在任何時候跳出數組。

示例:

Input: arr = [100,-23,-23,404,100,23,23,23,3,404]
Output: 3
Explanation: 你需要三次跳躍從索引 0 --> 4 --> 3 --> 9。注意索引 9 是數組的最後一個索引。

還是跳格子,給定一個數組,裡面會有一些具體的值,現在從 index = 0 的地方起跳,跳躍規則如下:

  1. 在 i+1 或 i-1 都在數組的範圍內

  2. 如果存在 index=j 且 arr [i]==arr [j] 且 i!=j 的時候,可以直接從 i 跳到 j

求從 index=0 跳到 index=arr.length-1 最小的次數

這題我還是沒 A,後面琢磨了下,一個搜索的題目

  1. 構建一個字典,值為 key,index 為 value(相同的值之間可以直接跳)

  2. 利用一個 set 來保存跳過的點

  3. 從 index = 0 開始進行 BFS ,求每個點在一步之內可以跳到哪個點,然後不斷的 BFS 直到到達終點

  4. 更新被訪問過的點

emmmm,好吧 BFS ,開寫吧

from typing import List, Set
import collections


class Solution:
    def minJumps(self, arr: List[int]) -> int:
        length = len(arr)
        if not arr or length == 1:
            return 0
        value_index = collections.defaultdict(list)
        for index, value in enumerate(arr):
            value_index[value].append(index)
        visited: Set[int] = set()
        traversal_queue = collections.deque([(0, 0)])
        result = 0
        while traversal_queue:
            next_step_queue = collections.deque()
            for _ in range(len(traversal_queue)):
                cur_index, cur_step = traversal_queue.popleft()
                cur_value = arr[cur_index]
                visited.add(cur_index)
                for next_index in [cur_index + 1, cur_index - 1] + value_index[
                    cur_value
                ]:
                    if (length > next_index >= 0) and (next_index not in visited):
                        if next_index == length - 2:
                            return cur_step + 2
                        if next_index == length - 1:
                            return cur_step + 1
                        next_step_queue.append((next_index, cur_step + 1))
                del value_index[cur_value]
            traversal_queue = next_step_queue
        return result

總結#

這周的題,還是簡單,但是需要小心,比如第二題我太大意直接暴力吃了一發 T,然後第三題沒仔細讀題(求最小的度數)吃了一發 WA,不過和第二天周賽比起來,真的是幸福,175 第三題的題面直接讓心態崩了,,明天寫題解。

好了,滾去睡覺

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