JAVA算法练习题day67

75.前K个高频元素

python 复制代码
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #堆排序
        count_dict = {}
        for n in nums:
            if n in count_dict:
                count_dict[n]+=1
            else:
                count_dict[n]=1
        
        #转(value,key)元组列表 等价items = list(count_dict.items())
        #这步太厉害了
        items = [(value,key) for key,value in count_dict.items()]

        #小顶堆up操作,只用和父节点比较
        def heap_up(heap,index):
            while index>0:
                father_index = (index-1)//2
                if heap[index][0]<heap[father_index][0]:
                    heap[index],heap[father_index] = heap[father_index],heap[index]
                    index = father_index
                else:
                    break
        
        #小顶堆down操作,在两个孩子之中找到最小,与其交换
        def heap_down(heap,index,size):
            minNum_index = index 
            l = index*2+1
            r = index*2+2
            #用size检查孩子是否越界
            if l<size and heap[minNum_index][0]>heap[l][0]:
                minNum_index = l
            if r<size and heap[minNum_index][0]>heap[r][0]:
                minNum_index = r
            if minNum_index!=index:
                #交换的是元祖,而不是元祖里面的某个元素(无法交换!)
                heap[minNum_index],heap[index] = heap[index],heap[minNum_index]
                heap_down(heap,minNum_index,size)
        
        def heap_push(heap,item):
            heap.append(item)
            heap_up(heap,len(heap)-1)

        def heap_pop(heap):
            if not heap:
                return None
            heap[0],heap[-1] = heap[-1],heap[0]
            item=heap.pop()
            heap_down(heap,0,len(heap))
            return item

        heap = []
        #遍历出现次数数组
        for value,key in items:
            if len(heap)<k:
                heap_push(heap,(value,key))
            else:
                if heap[0][0] < value:
                    heap_pop(heap)
                    heap_push(heap,(value,key))
                
        return [ key for (value,key) in heap ]
            

用快速选择来做:

python 复制代码
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #快速选择
        #与215数组中的第K个最大元素不同。这里元素会重复出现,需要去重,并且快速排序是根据元素的频率来排序该元素的。基准元素左边的元素频率大于基准元素的频率,基准元素右边的元素频率小于左边基准元素的频率
        freq = {}
        for n in nums:
            if n in freq:
                freq[n]+=1
            else:
                freq[n]=1
        # 提取所有唯一元素(待筛选)
        #这样写就会变成二维列表elements = [freq.keys()] 是错误的 会得到[[]]
        #写成这样可以 elements = [n for n in freq]取key 如果是取value [value for value in freq.values()]
        elements = list(freq.keys())
        n = len(elements)
        if n<=k:
            return elements
        def quick_select(elements,freq,k,l,r):
            if l>=r:
                return 
            x = elements[l]
            x_freq = freq[x]
            i,j=l-1,r+1
            while i<j:
                i+=1
                while freq[elements[i]]>x_freq:
                    i+=1
                j-=1
                while freq[elements[j]]<x_freq:
                    j-=1
                if i<j:
                    elements[i],elements[j] = elements[j],elements[i]

            if j >= k-1:
                quick_select(elements,freq,k,l,j)
            else:
                quick_select(elements,freq,k,j+1,r)
            
        quick_select(elements,freq,k,0,len(elements)-1)
        return elements[:k]

这是豆包写的堆解法,注释丰富,也可以当做手写堆排序的模板

python 复制代码
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        # 统计每个元素的出现次数
        count_dict = {}
        for num in nums:
            count_dict[num] = count_dict.get(num, 0) + 1
        
        # 转换为(次数, 元素)的列表
        items = [(freq, num) for num, freq in count_dict.items()]
        
        # 小顶堆的辅助函数:上浮操作(插入时维护堆性质)
        def heapify_up(heap, index):
            while index > 0:
                parent_index = (index - 1) // 2
                # 若当前节点的次数小于父节点,交换两者(小顶堆特性)
                if heap[index][0] < heap[parent_index][0]:
                    heap[index], heap[parent_index] = heap[parent_index], heap[index]
                    index = parent_index
                else:
                    break  # 无需继续上浮
        
        # 小顶堆的辅助函数:下沉操作(弹出堆顶后维护堆性质)
        def heapify_down(heap, index, size):
            while True:
                left_child = 2 * index + 1
                right_child = 2 * index + 2
                smallest = index  # 初始化最小值索引为当前节点
                
                # 找到左、右孩子中次数最小的节点
                if left_child < size and heap[left_child][0] < heap[smallest][0]:
                    smallest = left_child
                if right_child < size and heap[right_child][0] < heap[smallest][0]:
                    smallest = right_child
                
                # 若最小节点不是当前节点,交换并继续下沉
                if smallest != index:
                    heap[index], heap[smallest] = heap[smallest], heap[index]
                    index = smallest
                else:
                    break  # 无需继续下沉
        
        # 向堆中插入元素
        def heappush(heap, item):
            heap.append(item)
            heapify_up(heap, len(heap) - 1)  # 插入后上浮维护堆
        
        # 从堆中弹出堆顶元素(最小值)
        def heappop(heap):
            if not heap:
                return None
            # 交换堆顶与最后一个元素,便于弹出
            heap[0], heap[-1] = heap[-1], heap[0]
            item = heap.pop()  # 弹出原堆顶
            # 对新堆顶执行下沉维护堆
            heapify_down(heap, 0, len(heap))
            return item
        
        # 筛选前k个高频元素
        heap = []
        for freq, num in items:
            if len(heap) < k:
                # 堆未满,直接插入
                heappush(heap, (freq, num))
            else:
                # 堆已满,若当前元素次数大于堆顶,替换堆顶
                if freq > heap[0][0]:
                    heappop(heap)
                    heappush(heap, (freq, num))
        
        # 提取堆中的元素(前k个高频元素)
        return [num for (freq, num) in heap]

简单的调包做法:

python 复制代码
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #dict key是num,value是出现次数;对dict的value进行排序(查怎么操作),然后输出倒数K个dict的key
        #这样最差的时间复杂度是o(n^2)
        dict = {}
        for num in nums:
            if num in dict:
                dict[num] += 1
            else:
                dict[num] = 1

        sorted_dict = sorted(dict.items(), key=lambda x: x[1], reverse=True)
        ans = []
        for i in range(k):
            ans.append(sorted_dict[i][0])
        return ans
        #堆排序。
        #一个直观的做法是 对出现次数进行堆排序。可是要怎么建立次数到元素的映射呢?用草稿纸写一下:针对想到的数据结构都去模拟

自己实现其中的快速排序:

python 复制代码
class Solution(object):
    def quick_sort(self,arr,l,r):
        if l >= r:
            return
        x = arr[l][1]
        i,j = l-1,r+1
        while i<j:
            i+=1
            while arr[i][1]<x:
                i+=1
            j-=1
            while arr[j][1]>x:
                j-=1
            if i<j:
                #直接交换元组。这样是错的: arr[i][1],arr[j][1] = arr[j][1],arr[i][1]
                arr[i],arr[j] = arr[j],arr[i]
        self.quick_sort(arr,l,j)
        self.quick_sort(arr,j+1,r)

    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        #dict key是num,value是出现次数;对dict的value进行排序(查怎么操作),然后输出倒数K个dict的key
        #这样最差的时间复杂度是o(n^2)
        dict = {}
        for num in nums:
            if num in dict:
                dict[num] += 1
            else:
                dict[num] = 1
        dict = list(dict.items())
        self.quick_sort(dict,0,len(dict)-1)
        ans = []
        for i in range(len(dict)-1,len(dict)-1-k,-1):
            ans.append(dict[i][0])
        return ans
相关推荐
Kratzdisteln2 小时前
【TIDE DIARY 7】临床指南转公众版系统升级详解
python
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于java的民宿管理小程序为例,包含答辩的问题和答案
java·开发语言·小程序
それども2 小时前
List 添加元素提示 UnsupportedOperationException
java
ᐇ9592 小时前
Java集合框架:深入理解List与Set及其实现类
java·开发语言
无名-CODING2 小时前
Java集合List详解:从入门到精通
java·windows·list
陌路202 小时前
S15 排序算法--归并排序
数据结构·算法·排序算法
智者知已应修善业2 小时前
【c# 想一句话把 List<List<string>>的元素合并成List<string>】2023-2-9
经验分享·笔记·算法·c#·list
laplace01232 小时前
JAVA-Redis上
java·redis·spring
不要喷香水2 小时前
26.java openCV4.x 入门-Imgproc之图像尺寸调整与区域提取
java·人工智能·opencv·计算机视觉