【问题标题】:Highest frequency element in the dictionary字典中的最高频率元素
【发布时间】:2019-02-25 16:43:16
【问题描述】:

我正在尝试在给定中找到频率最高的元素,如下所示。

首先,我正在尝试构建一个字典并根据频率计算每个元素。

我不知道如何从构造的字典中提取最大值。

输入:[3,2,3]

输出:3

func majorityElement(_ nums1: [Int]) -> Int {

    var num1Dict = Dictionary(nums1.map{ ($0, 1) }, uniquingKeysWith : +)
    return num1Dict.values.max() // ????

}

【问题讨论】:

    标签: swift


    【解决方案1】:

    您已经正确构造了num1Dict,对于输入[3,2,3],它将是这样的:

    [2:1, 3:2]
    

    values.max() 将返回 2,因为在字典中的所有值(1 和 2)中,2 是最高的。

    现在看到你的错误了吗?

    您需要返回与最大值关联的键,而不是最大值。

    一个非常简单的方法是这样做:

    func majorityElement(_ nums1: [Int]) -> Int? { // you should probably return an optional here in case nums1 is empty
    
        let num1Dict = Dictionary(nums1.map{ ($0, 1) }, uniquingKeysWith : +)
        var currentHigh = Int.min
        var mostOccurence: Int?
        for kvp in num1Dict {
            if kvp.value > currentHigh {
                mostOccurence = kvp.key
                currentHigh = kvp.value
            }
        }
        return mostOccurence
    
    }
    

    【讨论】:

    • 有没有解决这个问题的速记(高阶函数)而不是使用for循环和if条件的组合?
    • @hotspring 是的,但是使用 for 循环是我能想到的最快的方法。对于更慢但更短的方式,请执行num1Dict.sorted(by: { $0.value > $1.value }).first!.key
    • 你也可以num1Dict.filter { $0.value == num1Dict.values.max() }.first!.key
    • @barbarity 是的,但请注意它的时间复杂度为 O(n^2)。
    • @Sweeper 我认为编译器足够聪明,知道num1Dict.values.max() 不会改变,但无论如何你总是可以做一行:let max = num1Dict.values.max() 然后num1dict.filter { $0.value == max }.first!.key
    【解决方案2】:

    您可以使用reduce(into:) 生成带有元素及其频率的Dictionary,然后使用这些频率对数组进行排序,然后简单地返回排序后数组的最后一个元素(基于升序)。

    extension Array where Element: Comparable & Hashable {
        func sortByNumberOfOccurences() -> [Element] {
            let occurencesDict = self.reduce(into: [Element:Int](), { currentResult, element in
                currentResult[element, default: 0] += 1
            })
            return self.sorted(by: { current, next in occurencesDict[current]! < occurencesDict[next]!})
        }
    
        func elementWithHighestFrequency() -> Element? {
            return sortByNumberOfOccurences().last
        }
    }
    

    免责声明:sortByNumberOfOccurences 方法是从another answer of mine 复制而来的。

    【讨论】:

      【解决方案3】:

      您要查找的内容(集合中最常见的元素)的数学名称称为模式。可能有联系(例如[1, 1, 2, 2, 3, 3] 有 3 种模式:[1, 2, 3]

      如果你想要任何一种模式(不关心具体是哪一种),你可以使用Dictionary.max(by:),你可以用它来找到计数最高的(元素,计数)对(即dict值)。然后,你可以得到这对的键,这将是模式元素。

      extension Sequence where Element: Hashable {
          func countOccurrences() -> [Element: Int] {
              return self.reduce(into: [:]) { (occurences, element) in occurences[element, default: 0] += 1}
          }
      
          func mode() -> Element? {
              return self.countOccurrences()
                  .max(by: { $0.value < $1.value })?
                  .key
          }
      
          func modes() -> [Element] {
              var firstModeNumOccurences: Int? = nil
              let modes = countOccurrences()
                  .sorted { pairA, pairB in pairA.value > pairB.value } // sorting in descending order of num occurences
                  .lazy
                  .prefix(while:) { (_, numOccurences) in
                      if firstModeNumOccurences == nil { firstModeNumOccurences = numOccurences }
                      return numOccurences == firstModeNumOccurences
                  }
                  .map { (element, _) in element }
      
              return Array(modes)
          }
      }
      
      print([1, 2, 3, 3, 4, 4].mode() as Any) // => 3 or 4, non-deterministic
      print([1, 2, 3, 3, 4, 4].modes() as Any) // => [3, 4]
      

      【讨论】:

      • 为什么使用Any
      • @Connor 解决类型错误是一件临时调试的事情。现已修复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多