计数数组中的位数(c++)



假设我有一个数组arr[5]={5,2,3,2,5},我为它写了以下程序

#include <iostream>
using namespace std;
int main()
{
int n;
cout<<"Enter Length of Elements= ";
cin>>n;
int arr[50];
for(int i=0;i<n;i++)
{
cout<<"Enter Number=";
cin>>arr[i];
}
for(int i=0;i<n;i++)
{
int countNum=1;

for(int j=i+1;j<n;j++)
{
if(arr[i]==arr[j])
{
if(i>0)
{
int countNum2=0;

for(int k=0;k>i;k++)
{
//bool repeat=false;
if(arr[i]==arr[k])
{
//repeat=false;
}
else
{
countNum2++;
}
}
if(countNum2==i)
{
countNum++;
}
}
else
{
countNum++;
}
}
else
{
for(int k=0;k<i;k++)
{
if(arr[k]==arr[i])
{
}
else
{
countNum=1;
}
}
}
}
cout<<arr[i]<<" has appeared "<<countNum<< "Times"<<endl;
}
return 0;
}

但为什么我5已经出现2次

2已经出现1次

3已经出现1次

2已经出现1次

5已经出现1次

而不是

5已经出现2次

2已经出现2次

3已经出现1次

那么如何修复我的程序帮助

这正是您所需要的(数组中每个数字的数量(:

// we'll store amounts of numbers like key-value pairs.
// std::map does exactly what we need. As a key we will
// store a number and as a key - corresponding counter
std::map<int, size_t> digit_count;
// it is simpler for explanation to have our
// array on stack, because it helps us not to
// think about some language-specific things
// like memory management and focus on the algorithm
const int arr[] = { 5, 2, 3, 2, 5 };
// iterate over each element in array
for(const auto elem : arr) 
{
// operator[] of std::map creates default-initialized
// element at the first access. For size_t it is 0.
// So we can just add 1 at each appearance of the number 
// in array to its counter.
digit_count[elem] += 1;
}
// Now just iterate over all elements in our container and
// print result. std::map's iterator is a pair, which first element
// is a key (our number in array) and second element is a value
// (corresponding counter)
for(const auto& elem : digit_count) {
std::cout << elem.first << " appeared " << elem.second << " timesn";
}

https://godbolt.org/z/_WTvAm

好吧,让我们写一些基本的代码,但首先让我们考虑一个算法(它不是最有效的,但更容易理解(:

最容易理解的方法是对数组中的每个数字进行迭代,并将相应的计数器递增一。让它是一对,第一个元素是我们的数字,第二个元素是计数器:

struct pair {
int number;
int counter;
};

算法的其他部分将在下面的代码中解释

// Say that we know an array length and its elements
size_t length = // user-defined, typed by user, etc.
int* arr = new int[length];
// input elements
// There will be no more, than length different numbers
pair* counts = new pair[length];
// Initialize counters
// Each counte will be initialized to zero explicitly (but it is not obligatory,
// because in struct each field is initialized by it's default
// value implicitly)
for(size_t i = 0; i < length; i++) {
counts[i].counter = 0;
}
// Iterate over each element in array: arr[i]
for(size_t i = 0; i < length; i++)
{
// Now we need to find corresponding counter in our counters.
size_t index_of_counter = 0;
// Corresponding counter is the first counter with 0 value (in case when
// we meet current number for the first time) or the counter that have
// the corresponding value equal to arr[i]
for(; counts[index_of_counter].counter != 0 && counts[index_of_counter].number != arr[i]; index_of_counter++)
; // Do nothing here - index_of_counter is incrementing in loop-statement
// We found an index of our counter
// Let's assign the value (it will assign a value
// to newly initialized pair and won't change anything
// in case of already existing value).
counts[index_of_counter].number = arr[i];
// Increment our counter. It'll became 1 in case of new
// counter, because of zero assigned to it a bit above.
counts[index_of_counter].counter += 1;
}
// Now let's iterate over all counters until we reach the first
// containing zero (it means that this counter and all after it are not used)
for(size_t i = 0; i < length && counts[i].counter > 0; i++) {
std::cout << counts[i].number << " appeared " << counts[i].counter << " timesn";
}
// correctly delete dynamically allocated memory
delete[] counts;
delete[] arr;

https://godbolt.org/z/hN33Pn

此外,它与std::map完全相同(相同的想法(,所以我希望它能帮助你理解第一个解决方案是如何在中工作的

代码的问题是,您不能删除重复项或分配一个数组,该数组可以有效地存储数组中每个唯一元素的计数。

同样,使用这么多循环也是完全没有必要的。

你只需要实现两个循环,外部循环遍历所有元素,内部循环首先检查重复(使用数组检查频率/出现状态(,并用一个变量作为计数器分别计算每个元素的出现次数。

用一个特定的值(比如零(设置一个计数器数组(具有所取数组的相应大小(,并在遍历数组时出现相同元素时更改该值,以触发不再计算该值。

然后,每当内部循环完成对整个数组的迭代时,将计数值从计数器变量转移到计数器数组(我们设置的用于区分重复项的数组(。(即将其放在数值计数后(

只要稍微修改一下,你的代码就会按照你想要的方式工作:

#include <iostream>
using namespace std;
int main()
{
int n;
cout<<"Enter Length of Elements = ";
cin>>n;
int arr[50];
for(int i=0;i<n;i++)
{
cout<<"Enter Number = ";
cin>>arr[i];
}
int counter[50];
for(int i=0; i<n; i++)
counter[i]=0;
// Our counter variable, but counts will be transferred to count[] later on:
int tempcount;
for(int i=0; i<n; i++)
{   // Each distinct element occurs once atleast so initialize to one:
tempcount = 1;
for(int j=i+1; j<n; j++)
{
// If dupe is found: 
if(arr[i]==arr[j])
{
tempcount++;
// Ensuring not to count frequency of same element again:
counter[j] = 1;
}
}
// If occurence of current element is not counted before:
if(counter[i] != 1)
counter[i] = tempcount;
}
for(int i=0; i<n; i++)
{
if(counter[i] != 0)
printf("%d has appeared %d times.n", arr[i], counter[i]);
}
return 0;
}

我使用一个变量tempcount来计数每个元素的出现次数,并使用一个初始化为零的数组count来首先检查重复项(通过将重复项设置为1,如果符合1则不计数(。然后,在每次外循环迭代时,我将计数的出现值从tempcount转移到counter[]。(针对所有独特元素(

最新更新