给定Q查询的类型为1、2、3和4,如下所述。
- 类型1:在列表中插入一个数字。
- 类型2:仅删除一次出现的数字(如果存在)。
- 类型3:打印出最不频繁的元素,如果存在多个元素,则打印其中最频繁的元素。
- Type-4:打印最频繁的元素,如果存在多个元素,则打印其中最小的元素。
任务是编写一个程序来执行上述所有查询。
例子:
Input:
Query1: 1 6
Query2: 1 6
Query3: 1 7
Query4: 3
Query5: 1 7
Query6: 2 7
Query7: 1 7
Query8: 3
Query9: 4
Output:
7
7
6
While answering Query4, the frequency of 6 is 2 and that of
7 is 1, hence the least frequent element is 7.
In Query8, the least frequent element is 6 and 7, so print the largest.
In Query9, the most frequent element is 6 and 7, so print the smallest.
天真的方法是使用任何Data-Structures(数组,向量,..)并存储所有元素。使用哈希表,可以存储每个元素的频率。在处理类型2的查询时,请从存储了元素的DS中删除该元素的一次出现。类型3和类型4的查询可以通过遍历哈希表来回答。每个查询的时间复杂度为O(N) ,其中N是DS中直到那时的元素数。
一种有效的方法是使用集合容器来回答每个查询。使用两组,一个哈希表,可以在每个查询的O(log n)中解决上述问题。使用了两组s1和s2 ,一组存储{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.
以下是解决每种类型的查询的算法:
- Type1:使用哈希表检查元素是否存在。如果不存在,则在哈希表中标记该数字。使用insert()在集合s1中插入{num,1},在集合2中插入{ 1,num} 。如果以前存在,则从哈希表中获取频率,并使用find()和delete()函数从set1中删除{num,frequency} ,并从set2中删除{frequency,num} 。在set1中插入{num,frequency + 1},在set2中插入{ frequency + 1,num} 。另外,增加哈希表中的计数。
- 类型2:请按照与上述查询类型1相同的过程进行操作。唯一的区别是减少哈希表中的计数,并在set1中插入{num,frequency-1},在set2中插入{frequency-1,num} 。
- Type3:打印可以使用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)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。