【LeetCode】Day34

前K个高频元素

在这里插入图片描述
解法1:哈希表+排序
一遍遍历统计各个元素的出现次数,再根据其出现次数对元素进行排序,输出排序后的Top-K元素。
代码略。
该方法的时间复杂度为 O(nlogn),其中n为nums的长度。

(进阶)
解法2:堆
一次遍历统计各个元素的出现次数,得到元素出现次数字典。但后续我们不用排序,而是利用堆的思想,构建一个小顶堆,大小为k。遍历元素出现次数字典元素,处理规则如下:

  • 若堆中元素小于k,则直接加入堆中。
  • 如果堆的元素个数等于 k,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 k 个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        num_dict = {}
        for num in nums:
            if num not in num_dict:
                num_dict[num] = 1
            else:
                num_dict[num] += 1
        heap = []
        l = k
        def build_heap(i, l):
            left, right = 2*i+1, 2*i+2
            min_index = i
            if left < l and heap[i][1] > heap[left][1]:
                min_index = left
            if right < l and heap[left][1] > heap[right][1] and heap[i][1] > heap[right][1]:
                min_index = right
            if min_index != i:
                heap[i], heap[min_index] = heap[min_index], heap[i]
                build_heap(min_index, l)
        # print(num_dict)
        for num in num_dict:
            if len(heap) < k:
            	# <k,则直接加入。
                heap.append((num,num_dict[num]))
                if len(heap) == k:
                	# 遍历其非叶子节点,构造小顶堆。
                    for i in range(k//2-1, -1, -1):
                        build_heap(i, l)
            else:
                if num_dict[num] > heap[0][1]:
                    # print(num, heap)
                    # 舍弃堆顶元素,并将新值插入堆中,重新调整小顶堆
                    heap[0] = (num, num_dict[num])
                    build_heap(0, l)
                    # print(heap)
        return [temp[0] for temp in heap]

该方法时间复杂度O(nlogk)其中k为堆大小。
关于堆相关原理可参考Python实现堆排序及原理详解 + TopK面试题(多图解释),但其代码在build_heap的找寻当前节点和左右子节点中的最小值有些问题。

字符的最短距离

在这里插入图片描述
解法:两次遍历+双指针
步骤如下:

  • 第一次遍历得到 c 在 s 中出现位置列表。
  • 维护两个指针left和right,分别指向c的当前位置和下一个位置。
  • 遍历s中元素,若等于c且索引大于right,则更新left和right指针至下一个位置。结果列表中+0
  • 若不等于c,则增加其与两个指针之间距离的最小值。
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        pos = []
        result = []
        for i, char in enumerate(s):
            if char == c:
                pos.append(i)
        i = 0
        # min(i+1, len(pos)-1)是解决s中只有一个c的情况
        left, right = pos[i], pos[min(i+1, len(pos)-1)]
        # print(pos)
        # print(left, right)
        for j, char in enumerate(s):
            if char == c:
                if j >= right and i < len(pos) - 2:
                    i += 1
                    left, right = pos[i], pos[i+1]
                # print(left, right)
                result.append(0)
                continue
            result.append(min(abs(j-left), abs(j-right)))
        return result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值