查找每个数组元素的频率
Find frequency of each array element
我有这个黑客级的事情要做。 N 必须<= 1 000 000。每个元素必须在 20 到 50 之间,但我不知道如何做到这一点,没有做过太多的竞争性编程。 用户输入 N 个数字。该程序查找每个元素的频率并降序打印它们。 我尝试做一个while循环(见main),但这不起作用。请帮忙。
输入格式:
9
42 42 3426 42 35 34 47 47
输出:
42 3
34 2
47 2
26 1
35 1
#include <iostream>
#include <algorithm>
using namespace std;
struct ele
{
int count, index, val;
};
bool mycomp(struct ele a, struct ele b) {
return (a.val < b.val);
}
bool mycomp2(struct ele a, struct ele b) {
if (a.count != b.count) return (a.count < b.count);
else return a.index > b.index;
}
void sortByFrequency(int arr[], int n)
{
struct ele element[n];
for (int i = 0; i < n; i++)
{
element[i].index = i;
element[i].count = 0;
element[i].val = arr[i];
}
stable_sort(element, element + n, mycomp);
element[0].count = 1;
for (int i = 1; i < n; i++)
{
if (element[i].val == element[i - 1].val)
{
element[i].count += element[i - 1].count + 1;
element[i - 1].count = -1;
element[i].index = element[i - 1].index;
}
else element[i].count = 1;
}
stable_sort(element, element + n, mycomp2);
for (int i = n - 1, index = 0; i >= 0; i--)
if (element[i].count != -1)
for (int j = 0; j < element[i].count; j++)
arr[index++] = element[i].val;
}
int main() {
int n; cin >> n;
int* arr = new int[n];
int* seen = new int[n];
for (int i = 0; i < n; i++){
while(arr[i] < 20 || arr[i] > 50)
cin >> arr[i];
}
sortByFrequency(arr, n);
for (int i = 0; i < n; i++) {
if (seen[i] == 0) {
int count = 0;
for (int j = i; j < n; j++)
if (arr[j] == arr[i]) {
count += 1;
seen[j] = 1;
}
cout << arr[i] << " " << count << endl;
}
}
}
并不是说我认为竞争性编程有助于提高编程技能。(至少,不是日常业务的编程技能。然而,我被诱惑了,无法抗拒。(今天是周一早上,可能是一周的一个很好的热身。
编译评论的想法,我得到了这个:
#include <cassert>
#include <iostream>
#include <vector>
#include <set>
int main()
{
// input and count frequency
int n; std::cin >> n;
assert(n >= 0 && n < 1000000);
const int valueMin = 20, valueMax = 50;
int freq[valueMax - valueMin + 1] {};
for (int i = 0; i < n; ++i) {
int value; std::cin >> value;
++freq[value - valueMin];
}
// sort frequency
std::set<std::pair<int, int>, bool(*)(const std::pair<int, int>&, const std::pair<int, int>&)>
freqSorted([](const std::pair<int, int> &pair1, const std::pair<int, int> &pair2) {
if (pair1.first != pair2.first) return pair1.first > pair2.first;
return pair1.second < pair2.second;
});
for (int i = valueMin; i <= valueMax; ++i) {
if (const int freqI = freq[i - valueMin]) {
freqSorted.insert(std::make_pair(freqI, i));
}
}
// output
for (std::pair<int, int> entry : freqSorted) {
std::cout << entry.second << ' ' << entry.first << 'n';
}
}
笔记:
我使用
const int valueMin = 20, valueMax = 50; int freq[valueMax - valueMin + 1] {};
以最小的内存占用量存储出现次数。(对输入值范围的明确限制鼓励了我。
user4581301 让我对内存消耗很敏感。(在阅读它之前,我没有意识到实际上没有必要存储输入值。
使用
std::map
(如毗湿奴达苏推荐的)也是我的第一个想法。在测试时,我想知道缺少结果,直到我意识到以出现次数为键的map
将仅存储具有相同频率的多个值之一。 因此,我将其更改为两个值作为键的std::set
。
输出:
42 3
34 2
47 2
26 1
35 1
科里鲁的现场演示
有时我想知道,可以为简单的任务编写多少行代码。无论如何。
有一种或多或少的标准方法可以对一般或容器中的某物进行计数。
我们可以使用关联容器,例如std::map
或std::unordered_map
.在这里,我们将一个"键"(在本例中为数字)与计数(在本例中为特定数字的计数)相关联。
幸运的是,地图有一个非常好的索引运算符[]。这将查找给定的键,如果找到,则返回对该值的引用。如果未找到,则它将使用键创建一个新条目,并返回对新条目的引用。因此,在这两种情况下,我们都将获得对用于计数的值的引用。然后我们可以简单地写:
std::unordered_map<int,unsigned int> counter{};
counter[value]++;
这看起来非常直观。
完成此操作后,您已经拥有频率表。要么按键(值)排序,要么使用std::map
排序,要么未排序,但可通过std::unordered_map
更快地访问。由于std::unordered_map
使用哈希,因此通常非常快。
现在您要根据频率/计数进行排序。不幸的是,这在地图上是不可能的。
因此,我们需要使用第二个容器,例如std::vector
,然后我们可以对任何给定谓词的取消std::sort
进行排序,或者,我们可以将值复制到容器中,例如隐式排序其元素的std::multiset
。
这就是我们将要做什么以及将产生一些非常紧凑的代码:
#include <iostream>
#include <utility>
#include <unordered_map>
#include <type_traits>
#include <set>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<int, unsigned int>;
// Standard approach for counter
using Counter = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Sorter = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
int main() {
// Read number of elements to check
if (int numberOfElements{}; std::cin >> numberOfElements) {
// Read and count
Counter counter{};
for (int i{}, value{}; (i < numberOfElements) && (std::cin >> value); counter[value]++, ++i);
// Sort
Sorter sorter(counter.begin(), counter.end());
// Show result
for (const auto& [value, count] : sorter) std::cout << value << ' ' << count << 'n';
}
}
- 数组元素打印的递归方法
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 为什么使用数组元素查找最大数字的程序不起作用?
- 数组元素更改值?
- 如何访问宏中定义的数组元素
- 将数组元素递增 1
- C++函数,它将数组、谓词和运算符作为参数,并将运算符应用于满足谓词的数组元素
- 存储指向动态数组元素的指针
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- 在 std::map 中插入数组元素
- 使用指针访问数组元素时出现意外结果
- c++ 使用动态分配运算符反向数组元素
- 为什么在 c++ 中分配 char 数组元素时,分配的字符会被销毁?
- 缺少数组元素问题
- 如何在类中制作 2D 数组元素,然后在其构造函数中指定其维度?
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 删除在结构 c++ 中声明的数组元素
- Getter 和 Setter 用于类 C++ 中的数组元素
- 尝试递归获取数组元素的总和
- 使用SWIG将numpy数组元素(int)传递给c++int