📌  相关文章
📜  查询插入、删除一个数字并打印最少和最频繁的元素

📅  最后修改于: 2021-10-27 08:23:28             🧑  作者: Mango

给定类型 1、2、3 和 4 的 Q 查询,如下所述。

  • 类型 1:在列表中插入一个数字。
  • 类型 2:如果存在,则仅删除一个数字。
  • Type-3:打印最不频繁的元素,如果存在多个元素,则打印其中最大的元素。
  • Type-4:打印最频繁的元素,如果存在多个元素,则打印其中最小的元素。

任务是编写一个程序来执行上述所有查询。

例子:

一种天真的方法是使用任何数据结构(数组、向量、..)并存储所有元素。使用哈希表,可以存储每个元素的频率。在处理类型 2 的查询时,从存储该元素的 DS 中删除该元素的一次出现。 type-3 和 type-4 的查询可以通过遍历哈希表来回答。每个查询的时间复杂度为O(N) ,其中 N 是 DS 中的元素数量。

一种有效的方法是使用 set 容器来回答每个查询。使用两组,一个哈希表,可以在每次查询的O(log n) 中解决上述问题。使用了两组s1s2 ,一组存储{num, frequency} ,而另一组存储{frequency, number} 。使用哈希映射来存储每个数字的频率。使用运算符重载设计集合 s2,使其按第一个元素的升序排序。如果第一个元素看起来与一个或多个元素相同,则集合将按第二个元素的降序排序。因此,用户定义的操作重载函数将是:

bool operator b.second;          
 return a.first < b.first;
}
Note: Operator overloading only works with user-defined 
data-types. pr is a struct which has first and second as two integers. 

以下是解决每种类型查询的算法:

  • 类型1:使用哈希表检查元素是否存在。如果不存在,则在哈希表中标记该数字。使用 insert() 在集合 s1 中插入{num, 1}和在 set2 中插入{1, num} 。如果之前存在,则从哈希表中获取频率并使用 find() 和 erase()函数从 set1 中删除{num, frequency}和从 set2 中删除{frequency, num} 。在 set1 中插入{num, frequency+1},在 set2 中插入{ frequency+1, num} 。另外,增加哈希表中的计数。
  • 类型 2:在查询类型 1 中执行与上述相同的过程。唯一的区别是减少哈希表中的计数并在 set1 中插入{num, frequency-1}和在 set2 中插入{frequency-1, num}
  • 类型 3:打印可以使用 begin()函数获取的开始元素,因为集合的设计方式是 begin() 返回最不频繁的元素。如果有多个,则返回最大的。
  • Type4:打印集合中的最后一个元素,可以使用集合中的 rbegin()函数获取。

下面是上述方法的实现:

// C++ program for performing 
// Queries of insert, delete one
//  occurrence of a number and 
// print the least and most frequent element
#include 
using namespace std;
  
// user-defined data-types
struct pr {
    int first;
    int second;
};
  
// user-defined function to
// design a set
bool operator<(pr a, pr b)
{
    if (a.first == b.first)
        return a.second > b.second;
    return a.first < b.first;
}
  
// declare a user-defined set
set s1, s2;
  
// hash map 
unordered_map m;
  
// Function to process the query
// of type-1
void type1(int num)
{
  
    // if the element is already there
    if (m[num]) {
  
        // get the frequency of the element
        int cnt = m[num];
  
        // returns an iterator pointing to
        // position where the pair is
        auto it1 = s1.find({ num, cnt });
        auto it2 = s2.find({ cnt, num });
  
        // deletes the pair from sets
        s1.erase(it1);
        s2.erase(it2);
  
        // re-insert the pair by increasing
        // frequency
        s1.insert({ num, m[num] + 1 });
        s2.insert({ m[num] + 1, num });
    }
  
    // if the element is not there in the list
    else {
  
        // insert the element with frequency 1
        s1.insert({ num, 1 });
        s2.insert({ 1, num });
    }
  
    // increase the count in hash-table
    m[num] += 1;
}
  
// Function to process the query
// of type-2
void type2(int num)
{
    // if the element exists
    if (m[num]) {
  
        // get the frequency of the element
        int cnt = m[num];
  
        // returns an iterator pointing to
        // position where the pair is
        auto it1 = s1.find({ num, cnt });
        auto it2 = s2.find({ cnt, num });
  
        // deletes the pair from sets
        s1.erase(it1);
        s2.erase(it2);
  
        // re-insert the pair by increasing
        // frequency
        s1.insert({ num, m[num] - 1 });
        s2.insert({ m[num] - 1, num });
  
        // decrease the count
        m[num] -= 1;
    }
}
  
// Function to process the query
// of type-3
int type3()
{
    // if the set is not empty
    // return the first element
    if (!s1.empty()) {
        auto it = s2.begin();
        return it->second;
    }
  
    else
        return -1;
}
  
// Function to process the query
// of type-4
int type4()
{
  
    // if the set is not empty
    // return the last element
    if (!s1.empty()) {
        auto it = s2.rbegin();
        return it->second;
    }
  
    else
        return -1;
}
// Driver Code
int main()
{
  
    // Queries
  
    // inserts 6, 6 and 7
    type1(6);
    type1(6);
    type1(7);
  
    // print the answer to query of type3
    cout << type3() << endl;
  
    // inserts 7
    type1(7);
  
    // deletes one occurrence of 7
    type2(7);
  
    // inserts 7
    type1(7);
  
    // print the answer to query of type3
    cout << type3() << endl;
  
    // print the answer to query of type4
    cout << type4() << endl;
  
    return 0;
}
输出:
7
7
6

时间复杂度:每个查询 O(log N)。
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程