Loading

【leetcode刷题tips】数字之间的关系

  • 由于数字之间的关系,在题目中有限定递增等类似条件时,还可以通过单调栈等类似思想再对算法进行时间复杂度的降维优化
  1. 1964. 找出到每个位置为止最长的有效障碍赛跑路线

    class Solution:
        def longestObstacleCourseAtEachPosition(self, obstacles: List[int]) -> List[int]:
            n = len(obstacles)
            st, dp = [], []
            for i in range(n):
                if not st or st[-1] <= obstacles[i]:
                    st.append(obstacles[i])
                    dp.append(len(st))
                else:
                    loc = bisect_right(st, obstacles[i])
                    dp.append(loc+1)
                    st[loc] = obstacles[i]
            return dp
                
    View Code

     单调栈+二分查找(bisect模块)

  2. 2030. 含特定字母的最小子序列

    class Solution:
        def smallestSubsequence(self, s: str, k: int, letter: str, repetition: int) -> str:
            n = len(s)
            right = [0] * (n+1)
            for i in range(n-1, -1, -1):
                right[i] = right[i+1] + (1 if s[i] == letter else 0)
            st = []
            cur_repetition = 0
            for i in range(n):
                while st and n - i + len(st) > k and st[-1] > s[i]:
                    if st[-1] == letter and cur_repetition + right[i] <= repetition:break
                    if st.pop() == letter:cur_repetition -= 1
                if len(st) < k:
                    if s[i] == letter or repetition - cur_repetition < k - len(st):
                        if s[i] == letter:cur_repetition += 1
                        st.append(s[i])
            return ''.join(st[:k])
    View Code

    限制条件单调栈

  • 利用数字特性降维查询
  1. class Solution:
        def minimumDifference(self, nums: [int]) -> int:
            n = len(nums) // 2
            sum_nums = sum(nums)
            nums.sort()
    
            def helper() -> {}:
                onesl, onesr = collections.defaultdict(set), collections.defaultdict(set)
                for i in range(1 << n):
                    cnt = 0
                    tmpl, tmpr = 0, 0
                    for j in range(n):
                        if i & 1 << j:
                            cnt += 1
                            tmpl += nums[j]
                            tmpr += nums[n+j]
                    onesl[cnt].add(tmpl)
                    onesr[cnt].add(tmpr)
                return onesl, onesr
    
            ans = inf
            left_ones, right_ones = helper()
    
            mean_sum = sum_nums>>1
            for i in range(n):
                lefts = sorted(left_ones[i])
                rights = sorted(right_ones[n - i])
                l, r = 0, len(rights) - 1
                while l < len(lefts) and r >= 0:
                    tmp = lefts[l] + rights[r]
                    ans = min(ans, abs(sum_nums - 2 * tmp))
    View Code

     状态压缩dp取值

    组合查询先排序成有序数组,再利用数字特性,双指针将组合从O(n**2)变为O(n)
  • 动态变化数组求最值也可利用单调栈的思想,利用一个标记元素是否存在的数据结构来辅助维护堆
  1. 2034. 股票价格波动

    class StockPrice:
    
        def __init__(self):
            self.stock = collections.defaultdict(int)
            self.time = -1
            self.minhp = []
            self.maxhp = []
            self.stock_cnt = collections.defaultdict(int)
    
        def update(self, timestamp: int, price: int) -> None:
            if timestamp in self.stock:self.stock_cnt[self.stock[timestamp]] -= 1
            self.stock[timestamp] = price
            self.time = max(self.time, timestamp)
            self.stock_cnt[price] += 1
            while self.minhp and not self.stock_cnt[self.minhp[0]]:
                heapq.heappop(self.minhp)
            heapq.heappush(self.minhp, price)
            while self.maxhp and not self.stock_cnt[-self.maxhp[0]]:
                heapq.heappop(self.maxhp)
            heapq.heappush(self.maxhp, -price)
    
        def current(self) -> int:
            return self.stock[self.time]
    
        def maximum(self) -> int:
            return -self.maxhp[0]
    
        def minimum(self) -> int:
            return self.minhp[0]
    View Code
posted @ 2021-10-14 15:40  ArkiWang  阅读(88)  评论(0编辑  收藏  举报