1. 程式人生 > 其它 >239. Sliding Window Maximum(Leetcode每日一題-2021.01.02)--抄答案

239. Sliding Window Maximum(Leetcode每日一題-2021.01.02)--抄答案

目錄

時間複雜度

  1. 線性時間複雜度演算法
    1. 單調棧
    2. 字首和
    3. 差分陣列
    4. 雙指標
    5. 滑動視窗

排序

桶排序

leetcode-164 最大間距

max_, min_ = max(nums), min(nums)
bucket_len = max(1, (max_ - min_) // (n - 1))       # 確定桶的長度 最小為1
bucket_num = (max_ - min_) // bucket_len + 1        # 確定桶的數量 要加一
buckets = [[] for _ in range(bucket_num)]           # 初始化所有桶

for num in nums:       # 將所有元素新增到桶內
    buckets[(num - min_) // bucket_len].append(num)

歸併排序

將陣列分為兩個子陣列,子陣列各自排序後再合併
leetcode-493 翻轉對

def merge(nums, lo, mid, hi): # 合併兩個排序好的陣列
    aux = nums[lo : hi + 1]             # 備份 儲存原始值
    i, j = lo, mid + 1        # 左右兩個子陣列的起點
    for k in range(lo, hi + 1): 
        if (i > mid):         # 左邊陣列已經全部合併
            nums[k] = aux[j - lo]
            j += 1
        elif (j > hi):        # 右邊陣列已經全部合併
            nums[k] = aux[i - lo]
            i += 1
        elif aux[i - lo] < aux[j - lo]:
            nums[k] = aux[i - lo]
            i += 1
        else:
            nums[k] = aux[j - lo]
            j += 1

def merge_sort(nums, lo, hi): # 歸併排序 包括lo到hi的全部數字 列表表示應該是range(lo, hi+1)
    if lo < hi:
        mid = (lo + hi) // 2
        merge_sort(nums, lo, mid)
        merge_sort(nums, mid+1, hi)
        merge(nums, lo, mid, hi)

二分

leetcode-4 尋找兩個正序陣列的中位數

回溯

leetcode-90 子集Ⅱ:集合去重
leetcode-842 將陣列拆分乘斐波那契序列

位運算

leetcode-5620 連線連續二進位制數字

a = a << 1 # 左移
a = a >> 1 # 右移
a = a & b  # 與
a = a | b  # 或
a = a ^ b  # 異或 若a等於b^c 則有b等於a^c
~a         # 非

數論

計算排列組合

leetcode-62 不同路徑

def C(total, t):
    ans = 1
    for i in range(1, t + 1):
        ans = ans * (total - i + 1) // i
    return ans

快速冪

時間複雜度O(logN)。
leetcode-50 Pow(x,n)

def myPow(x, n): # 計算x^n n>=0
    ans = 1.0
    x_contribute = x
    while n > 0:
        if n % 2 == 1:
            ans = ans * x_contribute
        x_contribute *= x_contribute
        n = n // 2
    return ans

線性篩

O(n)時間複雜度內找到小於n的素數。
leetcode-204 計數質數

def countPrimes(n):
    is_prime = [1] * n # 判斷當前數字是否為素數
    is_prime[0] = is_prime[1] = 0
    primes = []
    for i in range(2, n):
        if is_prime[i]:
            primes.append(i)
        for prime in primes:
            if prime * i < n:
                is_prime[prime * i] = 0
                if i % prime == 0: break # 後面的數一定可以被prime篩到 退出迴圈
            else: break # 後面的素數*i也一定大於n 退出迴圈 
    return len(primes)

動態規劃

leetcode-53 最大子序和
leetcode-188 買賣股票的最佳時機IV
狀態dp
leetcode-5619 最小不相容性

字串

找回文子串

動態規劃O(N^2 ),中心擴充套件O(N^2 ),Manacher演算法(N)
leetcode-5 最長迴文子串

資料結構

優先佇列

能夠完成下列操作的資料結構叫做優先佇列:
(1)插入一個數值
(2)取出最小的數值(獲得數值,並且刪除)
使用堆來進行解決,準確的說是二叉堆。
leetcode-1046 最後一塊石頭的重量

leetcode-402 移掉K位數字
leetcode-316 去除重複字母

單調棧

線性時間複雜度下,維護一個單調遞增或者遞減的棧。
在原始順序下,針對每一個元素找到下一個恰好大於或小於它的元素。
leetcode-42 接雨水
leetcode-84 柱狀圖中的最大矩形
leetcode-85 最大矩形
leetcode-321 拼接最大數
leetcode-5614 找出最具競爭力的子序列
leetcode-239 滑動視窗最大值

stack = []
heights = [0] + heights + [0] # 處理好邊界
ans = 0
for i in range(len(heights)):
    while stack and heights[stack[- 1]] > heights[i]:
        cur = stack.pop()
        ans = max(ans, heights[cur] * (i - 1 - stack[-1])) # 出棧時進行相應計算
    stack.append(i)
return ans

二叉搜尋樹

二叉搜尋樹能夠高效進行如下操作:
(1)插入一個數值
(2)查詢是否包含某個數值
(3)刪除某個數值
二叉搜尋樹所有的節點滿足左子樹上的所有節點都比自己小,右子樹上的所有節點都比自己大。
leetcode-98 驗證二叉搜尋樹

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

# 二叉樹的中序遍歷
stack = []
while stack or root:
    while root:
        stack.append(root)
        root = root.left
    root = stack.pop()
    print(root.val)
    root = root.right

字典樹

利用巢狀雜湊表來構建字典樹
0-1字典樹
leetcode-421 陣列中兩個數的最大異或值

並查集

一種管理元素分組情況的資料結構,可以高效的進行一下操作:
(1)查詢元素a和元素b是否屬於同一組
(2)合併元素a和元素b所在的組