1

I have a row of ten numbers for example:

5 5 6 7 5 9 4 2 2 7

Now I want a program that finds all duplicates and gives them out in the console like 3 times 5, 2 times 2, 2 times 7. While I did code an algorithm that finds duplicates in a row of numbers I can't give them out in the console as described. My program will output:

3 times 5
2 times 5
2 times 7
2 times 2

How can I solve this problem?

#include <iostream>

using namespace std;

int main()
{
  int arr[10];
  int i,j;
  int z = 1;

    for(i = 0; i < 10; i++) {
        cin >> arr[i];
    }
    for(i = 0; i < 10; i++){
        for(j = i+1; j < 10; j++){
            if(arr[i] == arr[j]){
                z++;
            }
        }
        if(z >= 2){
        cout << z << " times " << arr[i] << endl;
        z = 1;
        }

    }


    return 0;
}
4
  • make another array and increase indexes as you meet that index Commented Nov 24, 2017 at 9:09
  • You have to check that number is not present before. Commented Nov 24, 2017 at 9:09
  • Can you sort array or create additional structure (as std::map)? Commented Nov 24, 2017 at 9:10
  • std::map is your friend. Commented Nov 24, 2017 at 9:12

6 Answers 6

1

You can use the STL here (C++11):

int arr[10];
std::map<int, int> counters;

for (auto item : arr)
{
    cin >> item;
    ++counters[item];
}

std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
    if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, didn't catch that. Edited my answer to include that constraint
0

You need to check that arr[i] is not already found before, like this for example:

if(z >= 2) {
    int found_before = 0;
    for(j = 0; j < i; ++j)
        if(arr[i] == arr[j])
            found_before = 1;
    if(!found_before)
        cout << z << " times " << arr[i] << endl;
    z = 1;
}

which will print:

3 times 5
2 times 7
2 times 2

That way you don't print 5 again.

With your code it would print that it found 5 three times (for the first 5 in your array), and then when it would move to he second 5 in your array, it would forgot about the first 5 in your array, and report that it found 5 twice (itself and the 5th number of the array).

Comments

0

Why not use STL?

std::map<int, int> counter;
for (i = 0; i < 10; i++)
        counter[arr[i]] ++;
for (i = 0; i < 10; i++) {
    if (counter.count(arr[i]) > 0){
        std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
        counter.erase(arr[i]);
    }
}

std::map is a convenient tool for this job. You can easily count up occurrences of a specific number. After counting, you can print the count of each array element. With counter.erase, it's guaranteed that you won't print the same element for multiple times.

7 Comments

if (counter.count(arr[i]) == 0) counter[i] = 1; else is unneeded.
@Jarod42 Absent key treated as zero?
m[key] is equivalent to m.insert(key ValueType{}).second. so create default value which is 0 for int.
May I suggest a more readable for (auto n : arr) ++counter[n]?
And finally, since OP only wants duplicates values, >0 should be >1, and it would be more logical to iterate over the map than the array. You even could remove all ones from it (maybe).
|
0

Why keeping your algorithm idea, I suggest to create sub method:

std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
{
    std::size_t res = 0;
    for (std::size_t i = start; i != end; ++i) {
        if (arr[i] == value) {
            ++res;
        }
    }
    return res;
}

then your fixed algorithm would be:

for (std::size_t i = 0; i != 10; ++i) {
    if (count(arr, 0, i, arr[i]) != 0) {
        continue; // Already visited
    }
    auto total = count(arr, i, 10, arr[i]);
    if(total >= 2){
        std::cout << z << " times " << arr[i] << std::endl;
    }
}

Comments

0

An easy way is to make another array for it, especially if the numbers are not that big.

Lets say you have initialized your array like so: int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }

int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
for(int i = 0; i < 10; i++) {
    result[nums[i]]++;
}

for(int i = 0; i < max(nums); i++) {
    if (result[i] > 1) cout << result[i];
}

Mind you this isn't optimized for memory. For larger number contents you might want to consider hashmaps.

2 Comments

Now count this array: {0, 1, 2, 3, INT_MAX}.
I am fully aware of that and had recommended using hashmaps.
0

If you don't need performance but rather compact code, then std::multiset with std::upper_bound is an alternative:

#include<set>
#include<iostream>
#include<algorithm>

int main(int a, char** b)
{
  int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};

  std::multiset<int> a(std::begin(array), std::end(array));
  for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
  {
    if(a.count(*it) > 1)
        std::cout << *it << " times " << a.count(*it) << std::endl;
  }

  return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.