返回介绍

solution / 2600-2699 / 2671.Frequency Tracker / README

发布于 2024-06-17 01:03:01 字数 8822 浏览 0 评论 0 收藏 0

2671. 频率跟踪器

English Version

题目描述

请你设计并实现一个能够对其中的值进行跟踪的数据结构,并支持对频率相关查询进行应答。

实现 FrequencyTracker 类:

  • FrequencyTracker():使用一个空数组初始化 FrequencyTracker 对象。
  • void add(int number):添加一个 number 到数据结构中。
  • void deleteOne(int number):从数据结构中删除一个 number 。数据结构 可能不包含 number ,在这种情况下不删除任何内容。
  • bool hasFrequency(int frequency): 如果数据结构中存在出现 frequency 次的数字,则返回 true,否则返回 false

 

示例 1:

输入
["FrequencyTracker", "add", "add", "hasFrequency"]
[[], [3], [3], [2]]
输出
[null, null, null, true]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.add(3); // 数据结构现在包含 [3]
frequencyTracker.add(3); // 数据结构现在包含 [3, 3]
frequencyTracker.hasFrequency(2); // 返回 true ,因为 3 出现 2 次

示例 2:

输入
["FrequencyTracker", "add", "deleteOne", "hasFrequency"]
[[], [1], [1], [1]]
输出
[null, null, null, false]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.add(1); // 数据结构现在包含 [1]
frequencyTracker.deleteOne(1); // 数据结构现在为空 []
frequencyTracker.hasFrequency(1); // 返回 false ,因为数据结构为空

示例 3:

输入
["FrequencyTracker", "hasFrequency", "add", "hasFrequency"]
[[], [2], [3], [1]]
输出
[null, false, null, true]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.hasFrequency(2); // 返回 false ,因为数据结构为空
frequencyTracker.add(3); // 数据结构现在包含 [3]
frequencyTracker.hasFrequency(1); // 返回 true ,因为 3 出现 1 次

 

提示:

  • 1 <= number <= 105
  • 1 <= frequency <= 105
  • 最多调用 adddeleteOnehasFrequency 共计 2 * 105

解法

方法一:哈希表

我们定义两个哈希表,其中 $cnt$ 用于记录每个数字出现的次数,而 $freq$ 用于记录每个出现次数的数字的个数。

对于 add 操作,我们直接将哈希表 $freq$ 中 $cnt[number]$ 对应的值减一,然后将 $cnt[number]$ 加一,再将 $freq[cnt[number]]$ 对应的值加一。

对于 deleteOne 操作,我们首先判断 $cnt[number]$ 是否大于零,如果大于零,我们将哈希表 $freq$ 中 $cnt[number]$ 对应的值减一,然后将 $cnt[number]$ 减一,再将 $freq[cnt[number]]$ 对应的值加一。

对于 hasFrequency 操作,我们直接返回 $freq[frequency]$ 是否大于零。

时间复杂度方面,由于我们使用了哈希表,因此每个操作的时间复杂度均为 $O(1)$。空间复杂度 $O(n)$,其中 $n$ 为不同的数字的个数。

class FrequencyTracker:
  def __init__(self):
    self.cnt = defaultdict(int)
    self.freq = defaultdict(int)

  def add(self, number: int) -> None:
    self.freq[self.cnt[number]] -= 1
    self.cnt[number] += 1
    self.freq[self.cnt[number]] += 1

  def deleteOne(self, number: int) -> None:
    if self.cnt[number]:
      self.freq[self.cnt[number]] -= 1
      self.cnt[number] -= 1
      self.freq[self.cnt[number]] += 1

  def hasFrequency(self, frequency: int) -> bool:
    return self.freq[frequency] > 0


# Your FrequencyTracker object will be instantiated and called as such:
# obj = FrequencyTracker()
# obj.add(number)
# obj.deleteOne(number)
# param_3 = obj.hasFrequency(frequency)
class FrequencyTracker {
  private Map<Integer, Integer> cnt = new HashMap<>();
  private Map<Integer, Integer> freq = new HashMap<>();

  public FrequencyTracker() {
  }

  public void add(int number) {
    freq.merge(cnt.getOrDefault(number, 0), -1, Integer::sum);
    cnt.merge(number, 1, Integer::sum);
    freq.merge(cnt.get(number), 1, Integer::sum);
  }

  public void deleteOne(int number) {
    if (cnt.getOrDefault(number, 0) > 0) {
      freq.merge(cnt.get(number), -1, Integer::sum);
      cnt.merge(number, -1, Integer::sum);
      freq.merge(cnt.get(number), 1, Integer::sum);
    }
  }

  public boolean hasFrequency(int frequency) {
    return freq.getOrDefault(frequency, 0) > 0;
  }
}

/**
 * Your FrequencyTracker object will be instantiated and called as such:
 * FrequencyTracker obj = new FrequencyTracker();
 * obj.add(number);
 * obj.deleteOne(number);
 * boolean param_3 = obj.hasFrequency(frequency);
 */
class FrequencyTracker {
public:
  FrequencyTracker() {
  }

  void add(int number) {
    freq[cnt[number]]--;
    cnt[number]++;
    freq[cnt[number]]++;
  }

  void deleteOne(int number) {
    if (cnt[number]) {
      freq[cnt[number]]--;
      cnt[number]--;
      freq[cnt[number]]++;
    }
  }

  bool hasFrequency(int frequency) {
    return freq[frequency] > 0;
  }

private:
  unordered_map<int, int> cnt;
  unordered_map<int, int> freq;
};

/**
 * Your FrequencyTracker object will be instantiated and called as such:
 * FrequencyTracker* obj = new FrequencyTracker();
 * obj->add(number);
 * obj->deleteOne(number);
 * bool param_3 = obj->hasFrequency(frequency);
 */
type FrequencyTracker struct {
  cnt  map[int]int
  freq map[int]int
}

func Constructor() FrequencyTracker {
  return FrequencyTracker{map[int]int{}, map[int]int{}}
}

func (this *FrequencyTracker) Add(number int) {
  this.freq[this.cnt[number]]--
  this.cnt[number]++
  this.freq[this.cnt[number]]++
}

func (this *FrequencyTracker) DeleteOne(number int) {
  if this.cnt[number] > 0 {
    this.freq[this.cnt[number]]--
    this.cnt[number]--
    this.freq[this.cnt[number]]++
  }
}

func (this *FrequencyTracker) HasFrequency(frequency int) bool {
  return this.freq[frequency] > 0
}

/**
 * Your FrequencyTracker object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Add(number);
 * obj.DeleteOne(number);
 * param_3 := obj.HasFrequency(frequency);
 */
class FrequencyTracker {
  private cnt: Map<number, number>;
  private freq: Map<number, number>;

  constructor() {
    this.cnt = new Map();
    this.freq = new Map();
  }

  add(number: number): void {
    const f = this.cnt.get(number) || 0;
    this.freq.set(f, (this.freq.get(f) || 0) - 1);
    this.cnt.set(number, f + 1);
    this.freq.set(f + 1, (this.freq.get(f + 1) || 0) + 1);
  }

  deleteOne(number: number): void {
    const f = this.cnt.get(number) || 0;
    if (f > 0) {
      this.freq.set(f, (this.freq.get(f) || 0) - 1);
      this.cnt.set(number, f - 1);
      this.freq.set(f - 1, (this.freq.get(f - 1) || 0) + 1);
    }
  }

  hasFrequency(frequency: number): boolean {
    return (this.freq.get(frequency) || 0) > 0;
  }
}

/**
 * Your FrequencyTracker object will be instantiated and called as such:
 * var obj = new FrequencyTracker()
 * obj.add(number)
 * obj.deleteOne(number)
 * var param_3 = obj.hasFrequency(frequency)
 */
use std::collections::HashMap;

struct FrequencyTracker {
  cnt: HashMap<i32, i32>,
  freq: HashMap<i32, i32>,
}

/**
 * `&self` means the method takes an immutable reference.
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl FrequencyTracker {
  fn new() -> Self {
    FrequencyTracker {
      cnt: HashMap::new(),
      freq: HashMap::new(),
    }
  }

  fn add(&mut self, number: i32) {
    let count = self.cnt.entry(number).or_insert(0);
    let prev_freq = self.freq.entry(*count).or_insert(0);
    *prev_freq -= 1;
    *count += 1;
    let new_freq = self.freq.entry(*count).or_insert(0);
    *new_freq += 1;
  }

  fn delete_one(&mut self, number: i32) {
    if let Some(count) = self.cnt.get_mut(&number) {
      if *count > 0 {
        if let Some(prev_freq) = self.freq.get_mut(count) {
          *prev_freq -= 1;
        }
        *count -= 1;
        if let Some(new_freq) = self.freq.get_mut(count) {
          *new_freq += 1;
        }
      }
    }
  }

  fn has_frequency(&self, frequency: i32) -> bool {
    self.freq.get(&frequency).map_or(false, |&freq| freq > 0)
  }
}/**
 * Your FrequencyTracker object will be instantiated and called as such:
 * let obj = FrequencyTracker::new();
 * obj.add(number);
 * obj.delete_one(number);
 * let ret_3: bool = obj.has_frequency(frequency);
 */

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文