刷题笔记 739. 每日温度 (单调栈),215. 数组中的第K个最大元素(堆),347.前 K 个高频元素

739. 每日温度 (单调栈). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/daily-temperatures/description/?envType=study-plan-v2&envId=top-100-liked

class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        stack = [0]
        answer = [0] * len(temperatures)
        for i in range(1,len(temperatures)):
            if temperatures[i] <= temperatures[stack[-1]]:
                stack.append(i)
            else:
                while len(stack) != 0 and temperatures[stack[-1]] < temperatures[i]:
                    answer[stack[-1]] = i - stack[-1]
                    stack.pop()
                stack.append(i)
        return answer
                

第一次刷有思路,但是写不出来卡在细节处理,忘记把最后的stack.appned(i)加上,因为要把新遍历的比原先大的数放在栈顶。

这题的思路其实不难,写题应该是要先看出要用什么技巧,然后再找到对应的数据结构。而不是知道要用栈,再去硬套。

我们来分析一下,要找出数组位置下一个比这个位置更大的值与其之间的距离。例如其中的一步什么来看:

要是找到一个比之前小的数字,我们需要把小数字保存起来,因为他们也要找后续比她们更大的数。在找到后续比之前大的数字,前面的数值也就找到了比他们本身更大的数。因此可以不用保存状态了。这就需要用到保存状态的数据结构,我们自然而然就联想到了栈。栈可以存入之前的状态,经过条件判断后还可以弹出不惜要的状态。所以我们选择栈,并且此题用的是单调栈,保证了题目中需要的条件。

215. 数组中的第K个最大元素icon-default.png?t=N7T8https://leetcode.cn/problems/kth-largest-element-in-an-array/

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def quick_select(nums, k):
            # 随机选择基准数
            pivot = random.choice(nums)
            big, equal, small = [], [], []
            for num in nums:
                if num > pivot:
                    big.append(num)
                elif num < pivot:
                    small.append(num)
                else:
                    equal.append(num)
            if k <= len(big):
                return quick_select(big,k)
            if len(nums) - len(small) < k:
                # 第 k 大元素在 small 中,递归划分
                return quick_select(small, k - len(nums) + len(small))
            return pivat
        
        return quick_select(nums,k)
    
        

快速排序的核心包括“哨兵划分” 和 “递归” 。

哨兵划分: 以数组某个元素(一般选取首元素)为基准数,将所有小于基准数的元素移动至其左边,大于基准数的元素移动至其右边。
递归: 对 左子数组 和 右子数组 递归执行 哨兵划分,直至子数组长度为 1 时终止递归,即可完成对整个数组的排序。
下图展示了数组 [2,4,1,0,3,5] 的快速排序流程。

「快速选择」:设 N 为数组长度。根据快速排序原理,如果某次哨兵划分后,基准数的索引正好是 N−k ,则意味着它就是第 k 大的数字 。此时就可以直接返回它,无需继续递归下去了。

然而,对于包含大量重复元素的数组,每轮的哨兵划分都可能将数组划分为长度为 1 和 n−1 的两个部分,这种情况下快速排序的时间复杂度会退化至 O(N 2 ) 。

一种解决方案是使用「三路划分」,即每轮将数组划分为三个部分:小于、等于和大于基准数的所有元素。这样当发现第 k 大数字处在“等于基准数”的子数组中时,便可以直接返回该元素。

为了进一步提升算法的稳健性,我们采用随机选择的方式来选定基准数。

347.前 K 个高频元素

347. 前 K 个高频元素. - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/top-k-frequent-elements/submissions/548538519/?envType=study-plan-v2&envId=top-100-liked

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 使用字典统计数字出现次数
        time_dict = defaultdict(int)
        for num in nums:
            time_dict[num] += 1
        # 更改字典,key为出现次数,value为相应的数字的集合
        index_dict = defaultdict(list)
        for key in time_dict:
            index_dict[time_dict[key]].append(key)
        # 排序
        key = list(index_dict.keys())
        key.sort()
        result = []
        cnt = 0
        # 获取前k项
        while key and cnt != k:
            result += index_dict[key[-1]]
            cnt += len(index_dict[key[-1]])
            key.pop()

        return result[0: k]

 用字典来完成统计评率,再转换字典的key和value。重新排序后,获取前k项,注意有可能同评率的元素不唯一,所以需要用cnt来占位计算达到k个。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值