1. 程式人生 > >Leetcode 347:前K個高頻元素(最詳細解決方案!!!)

Leetcode 347:前K個高頻元素(最詳細解決方案!!!)

給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。

例如,

給定陣列 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]

注意:

  • 你可以假設給定的 k 總是合理的,1 ≤ k ≤ 陣列中不相同的元素的個數。
  • 你的演算法的時間複雜度必須優於 O(n log n) , n 是陣列的大小。

解題思路

這個問題的思路很簡單,首先建立一個木桶陣列,遍歷目標陣列,將資料放到木桶陣列中

1 : 1 1 1
2 : 2 2
3 : 3

我這裡的木桶陣列是通過dict實現的

class Solution:
    def topKFrequent(self, nums, k)
:
""" :type nums: List[int] :type k: int :rtype: List[int] """ count_list = dict() result = list() for i in nums: count_list[i] = count_list.get(i, 0) + 1 t = sorted(count_list.items(), key=lambda l : l[1] ,reverse=True
) for i in range(k): result.append(t[i][0]) return result

但是這種做法的時間複雜度是O(nlog(n)),並沒有達到題目的要求。那麼我們還有什麼辦法,我們可以使用一個priority_queue來儲存這k個元素,通過遍歷陣列,比較陣列中元素出現的頻率,然後實現入隊,出隊操作。

class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
from queue import PriorityQueue count_list = dict() for i in nums: count_list[i] = count_list.get(i, 0) + 1 p = PriorityQueue() for i in count_list.items(): if p.qsize() == k:# 判斷優先佇列長度是否滿足k if i[1] > p[0]:# bug p.get() p.put((i[1], i[0]))# 通過 (頻率,元素) 形式儲存 else: p.put((i[1], i[0])) result = list() while not p.empty(): _, v = p.get() result.append(v) return result

如你所見,上述程式碼是有問題的,我們無法通過index訪問PriorityQueue的元素。所以我們只能換個方法,可以使用heapq代替。

class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """   
        import heapq
        count_list = dict()
        for i in nums:
            count_list[i] = count_list.get(i, 0) + 1

        p = list()
        for i in count_list.items():
            if len(p) == k:
                if i[1] > p[0][0]:
                    heapq.heappop(p)
                    heapq.heappush(p, (i[1], i[0]))
            else:
                heapq.heappush(p, (i[1], i[0]))

        return [i[1] for i in p]

我們現在這個演算法的時間複雜度變成了O(nlog(k))。但是既然我們使用了heapq,那麼我們還有一種更加簡潔的寫法。

class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """   
        import heapq
        count_list = dict()
        for i in nums:
            count_list[i] = count_list.get(i, 0) + 1

        p = list()
        for i in count_list.items():
            heapq.heappush(p, (i[1], i[0]))

        return [i[1] for i in heapq.nlargest(k, p)]

但是這種寫法的時間複雜度比上面那種要高,因為我們在維護堆的時候,不再是維護k大小的堆,而是維護n大小的堆。

這個演算法還有缺陷,當我們的n == k的時候,演算法的時間複雜度就和第一種做法是一樣的了,還有沒有更好地解法?

我們可以把這個問題分開考慮,對與n > k,我們依舊使用上述的演算法,而對於n < k,我們就要想有什麼好的解法了。其實也很簡單,我們要清楚我們的PriorityQueue中裝的是什麼,我們通過維護一個n - k大小的PriorityQueue就可以實現。

我們想到的做法就是,維護一個n - k大小的最大堆,當進來一個元素,我們就將最大的那個元素彈出到result中即可。但是在python裡面我們的heapq沒法像c++中那樣可以修改比較函式,我們可以怎麼做呢?

class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """   
        import heapq
        count_list = dict()
        for i in nums:
            count_list[i] = count_list.get(i, 0) + 1

        p = list()
        result = list()
        for i in count_list.items():
            heapq.heappush(p, (-i[1], -i[0]))# tricks
            if len(p) > len(count_list) - k:
                _, val = heapq.heappop(p)
                result.append(-val)

        return result

一個更pythonic的解法

class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        from collections import Counter
        return [item[0] for item in Counter(nums).most_common(k)]     

如有問題,希望大家指出!!!

相關推薦

Leetcode 347:K高頻元素詳細解決方案

給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。 例如, 給定陣列 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]。 注意: 你可以假設給定的 k 總是合理的,1 ≤ k ≤ 陣列中不相同的元素的個數。 你的演算法的時間複雜

leetcode-347-K高頻元素(top k frequent elements)-java

題目及測試 package pid374; /* 前K個高頻元素 給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。 示例 1: 輸入: nums = [1,1,1,2,2,3], k = 2 輸出: [1,2] 示例 2: 輸入: nums = [1], k = 1 輸出

LeetCode 347. K高頻元素

給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。例如,給定陣列 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]。注意:你可以假設給定的 k 總是合理的,1 ≤ k ≤ 陣列中不相同的元素的個數。你的演算法的時間複雜度必須優於 O(n log n)

LeetCode題解】347_K高頻元素Top-K-Frequent-Elements

目錄 描述 解法一:排序演算法(不滿足時間複雜度要求) Java 實現 Python 實現 複雜度分析 解法二:最小堆 思路 Java 實現 Python 實現 複雜度分析 解法三:桶排序(bucket s

LeetCode——中級演算法——排序和搜尋——K高頻元素JavaScript

給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。 示例 1: 輸入: nums = [1,1,1,2,2,3], k = 2 輸出: [1,2] 示例 2: 輸入: nums = [1], k = 1 輸出: [1] 說明: 你可以假設給定的 k 總是合

LeetCode347. K高頻元素

題目描述 給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。 說明: 你可以假設給定的 k 總是合理的,且 1 ≤ k ≤ 陣列中不相同的元素的個數。 你的演算法的時間複雜度必須優於 O(n

LeetCode347. K高頻元素

參考知識:優先佇列      (通過最大堆實現的) 優先佇列的作用是能保證每次取出的元素都是佇列中權值最小的(Java的優先佇列每次取最小元素)。這裡牽涉到了大小關係,元素大小的評判可以通過元素本身的自然順序(natural ordering

Python:347. K高頻元素( Top K Frequent Elements)

class Solution(object): def topKFrequent(self, nums, k): d = {} res = [] for i in nums: if i in d.

Leetcode 27:移除元素詳細解決方案

給定一個數組 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。 不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。 元素的順序可以改變。你不需要考慮陣列中超出新長度後面的

Leetcode---K高頻元素--O(n)複雜度

前K個高頻元素 題目連結:前K個高頻元素 思路: 解法一: 首先對整個陣列排序,複雜度O(nlgn) 再對每個數字出現的頻度排序 最後找出前K個數字 解法二: 將陣列遍歷存入map集合中,value值存放出現次數 構造一個長度為

[LeetCode] Top K Frequent Elements K高頻元素

Given a non-empty array of integers, return the k most frequent elements. Example 1: Input: nums = [1,1,1,2,2,3], k = 2 Output: [1,2] Example 2:

K高頻元素

給定 assume clas 其中 span 復雜 top != int 給定一個非空的整數數組,返回其中出現頻率前 k 高的元素。 例如, 給定數組 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]。 註意: 你可以假設給定的 k 總是合理的,1 ≤

LeetCodeK高頻單詞【692】

LeetCode:前K個高頻單詞【692】 題目描述 給一非空的單詞列表,返回前 k 個出現次數最多的單詞。 返回的答案應該按單詞出現頻率由高到低排序。如果不同的單詞有相同出現頻率,按字母順序排序。 示例 1: 輸入: ["i", "love", "leetcode", "i",

LeetCode347. K高頻元素

今天繼續哈,寫的還是比較簡單的一個題,雜湊表和堆排序,要多多熟悉java的資料結構。題目給定一個非空的整數陣列,返回其中出現頻率前 k 高的元素。例如,給定陣列 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]。注意:你可以假設給定的 k 總是合理的,1 ≤

力扣——K高頻元素

hashmap 返回 add 算法 輸出 get contain 示例 urn 給定一個非空的整數數組,返回其中出現頻率前 k 高的元素。 示例 1: 輸入: nums = [1,1,1,2,2,3], k = 2 輸出: [1,2] 示例 2: 輸入: nu

Leetcode 25:k一組翻轉連結串列詳細解決方案

給出一個連結串列,每 k 個節點一組進行翻轉,並返回翻轉後的連結串列。 k 是一個正整數,它的值小於或等於連結串列的長度。如果節點總數不是 k 的整數倍,那麼將最後剩餘節點保持原有順序。 示例 : 給定這個連結串列:1->2->3->4-

Leetcode 230:二叉搜尋樹中第K小的元素詳細的解法

給定一個二叉搜尋樹,編寫一個函式 kthSmallest 來查詢其中第 k 個最小的元素。 說明: 你可以假設 k 總是有效的,1 ≤ k ≤ 二叉搜尋樹元素個數。 示例 1: 輸入: ro

Leetcode 82:刪除排序連結串列中的重複元素 II詳細解決方案

給定一個排序連結串列,刪除所有含有重複數字的節點,只保留原始連結串列中 沒有重複出現 的數字。 示例 1: 輸入: 1->2->3->3->4->4->5 輸

Leetcode 279:完全平方數詳細解決方案

給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入: n = 13

Leetcode 328:奇偶連結串列詳細解決方案

給定一個單鏈表,把所有的奇數節點和偶數節點分別排在一起。請注意,這裡的奇數節點和偶數節點指的是節點編號的奇偶性,而不是節點的值的奇偶性。 請嘗試使用原地演算法完成。你的演算法的空間複雜度應為 O(1),時間複雜度應為 O(nodes),nodes 為節點總數。