程式碼隨想錄演算法訓練營day11|150. 逆波蘭表示式求值 239. 滑動視窗最大值 347.前 K 個高頻元素

Tristan241001發表於2024-10-10

學習資料:https://programmercarl.com/0150.逆波蘭表示式求值.html#演算法公開課
棧、佇列、堆

學習記錄:
150.逆波蘭表示式求值(中序表示式轉換為後序表示式,用棧實現;遇到符號就從棧中取前兩個元素進行運算,再放回去)

點選檢視程式碼
from operator import add, sub, mul

def div(x, y):
    return int(x/y) if x*y > 0 else -(abs(x)//abs(y))

class Solution(object):
    op_map = {'+':add, '-':sub, '*':mul, '/':div}
    def evalRPN(self, tokens):
        """
        :type tokens: List[str]
        :rtype: int
        """
        stack=[]
        for token in tokens:
            if token not in self.op_map:
                stack.append(int(token))
            else:
                op2=stack.pop()
                op1=stack.pop()
                stack.append(self.op_map[token](op1, op2))
        return stack.pop()

239.滑動視窗最大值(自定義單調佇列的入隊出隊方式;當滑動窗格時,新加入的元素加入前,要先彈出隊尾小於它的元素保證單調性;每個窗格中最大值都放在隊頭)

點選檢視程式碼
from collections import deque

class MyQuee:
    """
    自定義單調佇列,包括他的入隊和出隊的規則
    """
    def __init__(self):
        self.queue = deque()
    
    # value出:若佇列不為空,且該值等於頭元素,則可出 (反正出的都是此時的最大值)
    def pop(self, value):
        if self.queue and value==self.queue[0]:
            self.queue.popleft()

    # value入:若隊不為空,且該值大於隊尾值,則迴圈刪除隊尾值,最後把該值加到隊尾 (保證佇列單調遞減)
    def push(self, value):
        while self.queue and value > self.queue[-1]:
            self.queue.pop()
        self.queue.append(value)

    # 提取佇列的頭元素,也就是此時的最大值
    def front(self):
        return self.queue[0]



class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        que = MyQuee()
        result = []
        for i in range(k):
            que.push(nums[i])        # 呼叫自定義入隊方式
        result.append(que.front())   # 呼叫自定義取出最大值方式
        for i in range(k, len(nums)):
            que.pop(nums[i-k])       # 呼叫自定義出隊方式,來移除滑動窗格離開的那個元素
            que.push(nums[i])         # 呼叫自定義入隊方式,來新增滑動窗格移入的那個元素
            result.append(que.front()) # 呼叫自定義取最大值方式,並把最大值保持到結果中
        return result


347.前K個高頻元素(用小頂堆,二叉樹越深值越大;保證先彈出的是最小值,留下的是前K個值)

點選檢視程式碼
import heapq      # 優先順序佇列,預設最小堆
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        # 統計(值:頻次)
        map_ = {}
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0)+1

        # 我猜是把新鍵值對加入最小堆,再把前k個以外的都彈出,(在最小堆裡,就是把根那部分彈出去)
        priority_que = []
        for key, freq in map_.items():
            heapq.heappush(priority_que, (freq, key))
            if len(priority_que) > k:
                heapq.heappop(priority_que)
        
        # 因為小頂堆是先彈出最小的,這裡專門倒序來輸出陣列
        result = [0]*k
        for i in range(k-1, -1, -1):
            result[i] = heappop(priority_que)[1]
        return result
        

PS:好難,聽卡哥講演算法就很容易理解,但是轉換為程式碼就難辦了,下次再學
很巧的是,今天準備海康威視筆試就學到了347題,哈哈哈
今天吃的煮泡麵、螺螄粉都好燙,今天的光啊

相關文章