print first repeating element using hashmap; - c++

#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_map<int,int>h;
int T;
int n,i;
cin>>T;
while(T--)
{ int flag=0;
cin>>n;
int arr[n];
for( i=0;i<n;i++)
{
cin>>arr[i];
}
for(i=0;i<n;i++)
{
h[i]=count(arr,arr+n,arr[i]);
}
for(auto x: h)
{
if(x.second>1)
{ flag=1;
cout<<x.first<<endl;
break;
}
}
if(flag==0)
{ cout<<-1<<endl;
}
}
}
Given an integer array. The task is to find the first repeating element in the array i.e., an element that occurs more than once and whose index of first occurrence is smallest.
I am getting infinite result. what am I don't wrong. the test cases are below
Input:
test case :1
array size:7
array(1 5 3 4 2 4 5 )
Output:
2

Since you're using an std::unordered_map, the approach should be very simple:
Set the minimum position to a large value.
Loop on the number data from first item to last.
If the number does not exist in the map, then
Add the item and position to the map
else
Set the minimum position to min(minimum position, position found in map)
There is no need for flag variables (which will almost always cause issues somewhere, and most likely the reason for your error), or a recount over and over again of the items in the original array like this:
for(i=0;i<n;i++)
{
h[i]=count(arr,arr+n,arr[i]);
}
If you had 1000 numbers, you would be calling this count loop 1000 times. That is very inefficient.
As to your implementation, where do you store the index of the first duplicate? I don't see it, unless it is hidden behind all of the manipulations you're doing with this flag variable. Whatever you're doing, it is wrong.
Here is an implementation, using your test data and using the outline I presented earlier:
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include <climits>
int main()
{
std::unordered_map<int, int> numbers;
int test[] = {1, 5, 3, 4, 2, 4, 5};
// Set minimum index to a large value
int minIndex = std::numeric_limits<int>::max();
for (size_t i = 0; i < std::size(test); ++i )
{
// check if item is found
auto iter = numbers.find(test[i]);
if ( iter == numbers.end())
// not found, so add item and position
numbers.insert({test[i], i});
else
// set the minimum index to the found position and exit the loop
minIndex = std::min(minIndex, iter->second);
}
if ( minIndex == std::numeric_limits<int>::max())
std::cout << -1;
else
std::cout << minIndex;
}
Output:
1
This is effectively has O(n) runtime, as opposed to what you wrote, which was O(n^2) due to the inefficient counting loop.

despite the question, this line of code
int arr[n];
is not allowed in C++ even if your local IDE didn't give any errors I think your online judge will give a runtime error.
As the arrays in C++ must be statically allocated which means you need to know the number of elements of the array before you run the code.

Related

Get number of same values in arrays in C++

I need a function int countDifferentNumbers(int v[], int n) which counts how many different values the array v with n entries contains.
Example:
It should return the result 3 for the array v = {1, 5, 5, 8, 1, 1} because the array contains only 3 different values.
This is how the code looks like so far:
int countDifferentNumbers(int v[], int n)
{
int counter = 0;
for(int i = 0; i < n; ++i)
{
for(int j = i; j < n; ++j)
{
if(v[i] == v[j + 1])
{
cout << "match" << endl;
counter++;
cout << v[i] << endl;
}
}
}
return counter;
}
I would appreciate an explanation of what is wrong in my function and how I need to redesign it.
Note: Unfortunately, I have not found a suitable thread for this either. All threads with my problems were solved in Java and Python languages.
Recently I see more and more answers here on SO that lead users in the wrong direction by giving bad answers.
Also, for C++, the question has already been answered in the comment by Igor Tandetnik, and that should finally be used.
But let me answer the question of the OP as asked. What is wrong with my function? OK, there are several aspects. Let us first look at the style.
You have 0 lines of comments, so the code quality is 0. If you would write comments, then you would already find most bugs by yourself, because then, you need to explain your own wrong statements.
Then please see your source code with my amendments. I added the problems as comment.
// This is just a dumped function and not a minimum reproducible example
// All header files are messing
// Obviously "using namespace std;" was used that should NEVER be done
// The function should retrun an unsigned value, best size_t, because a count can never be negative
// Same for n, that is the size of an array. Can also never be negative
// C-sytle arrays should NEVER be used in C++. NEVER. Use std::vector or std::array instead
int countDifferentNumbers(int v[], int n)
{
int counter = 0; // Now in C++ we can use braced initialzation instead of assignement
for (int i = 0; i < n; ++i)
{
for (int j = i; j < n; ++j)
{
if (v[i] == v[j + 1]) // Accessing out of bounds element
{
cout << "match" << endl; // Now endl needed here. Can all be done in one cout statement in one line
counter++; // Always counting up the same counter for all kind of double numbers.
cout << v[i] << endl;
}
}
}
return counter;
That was one point of the answer. But now the second point. Evene more important. The algorithm or the design is wrong. And finding the correct solution, this thinking before codingt, you need to do, before you write any line of code.
You obviously want to find the count of unique numbers in an array.
Then you could look what is already there on Stackoverflow. You would probaly find 20 answers already that coud give you a hint.
You could use std::unique. Please see here for a description. This function sounds like it does what you want, right? Some example implementation:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
std::sort(v.begin(), v.end()); // Sorting is precondition for std::unique
v.erase(std::unique(v.begin(), v.end()), v.end()); // Erase all non-unique elements
return v.size(); // Return the result
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // SHow result to user
return 0;
}
Then, we could count the occurence of each number in a std::map or std::unordered_map. And the number of counters will be the result. Example:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
std::unordered_map<int, size_t> counter{}; // Here we will count all occurences of different numbers
for (const int i : v) counter[i]++; // Iterate over vector and count different numbers
return counter.size(); // Count of different numbers
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // Show result to user
return 0;
}
But, then, thinking further, about what conatiners we could use, we will find out the answer from Igor Tandetnik. There are 2 containers that can hold unique values only. No double values. And these are: std::set and std::unordered_set., So, we can simply copy the data into one of those containers, and, only unique values will be stored there.
There are many ways to get the data into a set. But the simplest one is to use its range constructor. Then, we have unique elements, and, the containers size function will give the result:
See here: Constructor Number 2.
The result will be a function with one line like this
#include <iostream>
#include <unordered_set>
#include <vector>
// If you want to keep the original data, remove the reference-specifier &
size_t countDifferentNumbers(std::vector<int>& v) {
return std::unordered_set<int>(v.begin(), v.end()).size();
}
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << countDifferentNumbers(test) << '\n'; // Show result to user
return 0;
}
And since functions with one line are often not so usefull, we can also write the final solution:
#include <iostream>
#include <unordered_set>
#include <vector>
int main() {
std::vector test{ 1, 5, 5, 8, 1, 1 }; // Some test data
std::cout << std::unordered_set<int>(test.begin(), test.end()).size() << '\n'; // Show result to user
return 0;
}
So, by analyzing the problem and choosing the right algorithm and container and using C++, we come to the most easy solution.
Please enable C++17 for your compiler.
first sort the array v. if n >0 then initially there must be one number which is unique so just increment the value of counter once. then with loop check if the two consecutive number are same or not. if same do nothing else increment the value of counter.
if you are writing code in c then use qsort. #include <stdlib.h> add this in header and. use qsort() func
here is the code:
#include <bits/stdc++.h>
using namespace std;
int countDifferentNumbers(int v[] , int n)
{
int counter = 0;
sort(v, v+ n); // if you are writing code in c then just write a decent sort algorithm.
if (n>0 ){
printf("%d\n", v[0]);
counter ++;
}
for(int i = 0; i < n-1; ++i)
{
if(v[i] == v[i+1]){
continue;
} else {
printf("%d\n", v[i+1]);
counter++;
}
}
return counter;
}
int main()
{
int v[] = {1, 5, 5, 8, 1, 1};
int result = countDifferentNumbers(v,6);
printf("unique number %d", result );
return 0;
}

The three biggest numbers in array

#include<iostream>
using namespace std;
int main()
{
int s;
cin>>s;
int t=3;
int maxValue,imax[t],maxIndex,arr[s];
for(int i=0; i<s; i++){
cin>>arr[i];
}
maxValue=arr[0];
for(int i=0;i<s;i++){
if(arr[i]>maxValue){
maxValue=arr[i];
imax[0] = i;
}
}
maxValue=arr[0];
for(int i=0;i<s;i++){
if (i == imax[0]) { continue; }
if(arr[i]>maxValue){
maxValue=arr[i];
imax[1] = i;
}
}
maxValue=arr[0];
for(int i=0;i<s;i++){
if (i == imax[0]) { continue; }
if (i == imax[1]) { continue; }
if(arr[i]>maxValue){
maxValue=arr[i];
imax[2] = i;
}
}
cout<<"First biggest number:"<<arr[imax[0]]<<"\n";
cout<<"Second biggest number:"<<arr[imax[1]]<<"\n";
cout<<"Third biggest number:"<<arr[imax[2]];
return 0;
}
This program must return tree numbers which is biggest in this arraybut , i do not know why when I introduce as example five numbers (121,34,56,67,545) and the compiler was return 545 and then crash.
Thank you in advance for the answer.
The problem is that before iterating the loop, you first set the maxValue to be the first element in the array. The imax only gets updated whenever there is at least one element greater than the current maxValue. However, if the first element is somehow the maxValue you are looking for, then the imax never gets set, which would be uninitialized causing segmentation fault at the end.
In your code, after finding the largest element 545, the second largest element was never found, since 121 is the first element in the array. Hence after printing out 545, imax[1] is uninitialized and the program crashes.
You use uninitialized array values in lines
cout<<"First biggest number:"<<arr[imax[0]]<<"\n";
cout<<"Second biggest number:"<<arr[imax[1]]<<"\n";
cout<<"Third biggest number:"<<arr[imax[2]];
If there are less than 3 different numbers in input, some imax array elements will not be initialized. Also if input array is empty, imax will not be initialized at all.
Therefore in expression arr[imax[1]] you read element of arr with index, which was not initialized and can be some very big number. It can be fixed if you declare iarr as
int imax[t] = {};
This will zero-initialize all elements of array and will prevent crashing.
Your program also doesn't check number of elements in input array, so if there are less than three input numbers arr[2] will also print uninitialized value.
Here's proper solution using STL algorithms and std::vector. It works with any number of t - you can easily change it to print largest 10 numbers. It is also memory efficient - it does not need to store whole input array so you can process large inputs with it.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
int s;
std::cin >> s;
unsigned t = 3;
std::vector<int> max_numbers;
max_numbers.reserve(t + 1);
for (int i = 0; i < s; ++i) {
int number;
if (std::cin >> number) { //Check basic input errors
max_numbers.push_back(number); // Add number to top-3 list
// Sort elements in descending order
std::sort(max_numbers.begin(), max_numbers.end(), std::greater<int>());
// Remove duplicates
max_numbers.erase(std::unique(max_numbers.begin(), max_numbers.end()),
max_numbers.end());
// Remove excess elements
if (max_numbers.size() > t) {
max_numbers.resize(t);
}
}
}
std::cout << "Biggest " << t << " numbers are" << std::endl;
for (int i : max_numbers) {
std::cout << i << std::endl;
}
}

Sum of different numbers in an array

I want to have a function that returns the sum of different (non duplicate) values from an array: if I have {3, 3, 1, 5}, I want to have sum of 3 + 1 + 5 = 9.
My attempt was:
int sumdiff(int* t, int size){
int sum=0;
for (int i=0; i<=size;i++){
for(int j=i; j<=size;j++){
if(t[i]!=t[j])
sum=sum+t[i];
}
}
return sum;
}
int main()
{
int t[4]={3, 3, 1, 5};
cout << sumdiff(t, 4);
}
It returns 25 and I think I know why, but I do not know how to improve it. What should I change?
Put all the items in a set, then count them.
Sets are data structures that hold only one element of each value (i.e., each of their elements is unique; if you try to add the same value more than once, only one instance will be count).
You can take a look in this interesting question about the most elegant way of doing that for ints.
First of all, your loop should be for (int i=0; i<size;i++). Your actual code is accessing out of the bounds of the array.
Then, if you don't want to use STL containers and algorithms (but you should), you can modify your code as follows:
int sumdiff(int* t, int size){
int sum=0;
for (int i=0; i<size;i++){
// check if the value was previously added
bool should_sum = true;
for(int j=0; should_sum && j<i;j++){
if(t[i]==t[j])
should_sum = false;
}
if(should_sum)
sum=sum+t[i];
}
return sum;
}
int main()
{
int t[4]={3, 3, 1, 5};
cout << sumdiff(t, 4);
}
You could:
Store your array contents into an std::unordered_set first. By doing so, you'd essentially get rid of the duplicates automatically.
Then call std::accumulate to compute the sum
**wasthishelpful's answer was exactly what i was talking about. I saw his post after i posted mine.
So, you're trying to check the duplicate number using your inner loop.
However, your outer loop will loop 4 times no matter what which gives you wrong result.
Try,
Do only checking in inner loop. (use a flag to record if false)
Do your sum outside of inner loop. (do the sum when flag is true)
Here is another solution using std::accumulate, but it iterates over the original elements in the call to std::accumulate, and builds the set and keeps a running total as each number in the array is encountered:
#include <iostream>
#include <numeric>
#include <set>
int main()
{
int t[4] = { 3, 3, 1, 5 };
std::set<int> mySet;
int mySum = std::accumulate(std::begin(t), std::end(t), 0,
[&](int n, int n2){return n += mySet.insert(n2).second?n2:0;});
std::cout << "The sum is: " << mySum << std::endl;
return 0;
}
The way it works is that std::insert() will return a pair tbat determines if the item was inserted. The second of the pair is a bool that denotes whether the item was inserted in the set. We only add onto the total if the insertion is successful, otherwise we add 0.
Live Example
Insert array elements into a set and use the std::accumulate function:
#include <iostream>
#include <numeric>
#include <set>
int main()
{
int t[4] = { 3, 3, 1, 5 };
std::set<int> mySet(std::begin(t), std::end(t));
int mySum = std::accumulate(mySet.begin(), mySet.end(), 0);
std::cout << "The sum is: " << mySum << std::endl;
return 0;
}

Reversing an Array Results In SegFault

#include <iostream>
using namespace std;
/*
*
*/
int main() {
int k, in[k],reversea[k],i,m,n;
cin>>k;
for (i=0;i<k;i++){
cin>>in[i];
}
for (m=k-1;m>=0;m--){
for (n=0;n<k;n++){
in[m]=reversea[n];
}
}
for(i=0;i<k;i++){
cout<<reversea[i];
}
return 0;
}
I have no idea why it says segmentation fault even before i start debugging it. I compile another one on calculating the frequency of 1, 5, and 10 in an array of k numbers, and it says the same thing...
Here is the other one:
#include <iostream>
using namespace std;
int main() {
int k,i,m,n,count5,count1,count10;
int input[k];
cin>>k;
for (i=0;i<k;i++){
cin>>input[i];
}//input all the numbers
for(i=0;i<k;i++){
if (input[i]=1){
count1++;
}
if (input[i]=5){
count5++;
}
if (input[i]=10){
count10++;
}
}
cout<<count1<<"\n"<<count5<<"\n"<<count10<<"\n";
return 0;
}
Please help me. Thanks.
On this line
int k, in[k],reversea[k]
How are you supposed to initialize an array with k elements if k isn't initialized? The size of an array must be known at compile time not run time. If k isn't know until run time, use a std::vector
int k;
std::cin >> k;
std::vector<int> in(k);
std::vector<int> reversea(k);
Both your programs have two major faults.
You need to know the size of an array while creating it. In your code, k is still uninitialized and you are using this value as the size of your array. Instead, change it to
int k,i,m,n;
cin >> k;
int in[k];
int reversea[k];
While reversing the array, you should be filling reversea using values from in, and not the other way round. Also, you don't need 2 for loops, just use 1 for loop.
for (m=k-1; m>=0; m--){
reversea[m] = in[k-1-m];
}
In the second program, you again need to get the value of k before creating the array input[k].
You are testing for equality with a = instead of == . Change your code from
if (input[i]=1){
to
if (input[i] == 1) {

C++ generating random numbers without repetition .output screen is just blank with a blinking cursor

My intention is to generate random numbers from 1 to 9 without repetition
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
int randrange(int low,int high) /* generates a random number within given range*/
{
return rand()%(low+high)+low+1;
}
int main()
{
int num[9]={0},i,j;
bool check;
for(i=0;i<9;i++)
{
check=false;
do
{
num[i]=randrange(1,9);
for(j=0;j<i;j++)
{
if( num[i]==num[j]) // checks whether number already exists in the array
check=false;
else
check=true;
}
} while(check==false);
}
// the program is working fine without the repetition check
// this section prints out the array elements
for(i=0;i<9;i++)
{
cout<<num[i]<<" ";
}
return 0;
}
Just generate the numbers 1 to 9, then shuffle them randomly using std::random_shuffle.
int nums[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::random_shuffle(nums, nums + 9);
This will leave nums with the numbers from 1 to 9 in random order, with no repetitions.
Your duplicate checking loop has a flaw: the check is set to the result of checking the last pair of values, rather than the result of checking all the preceding pairs.
You need to set check = true before the inner loop, then proceed to verifying all items from zero to i-1. If the check becomes false at any point, stop the loop:
check = true;
for (j = 0 ; (check) && (j < i) ; j++) {
check = (num[i] != num[j]);
}
In addition, you need to fix the randrange, because your current implementation returns values in range 2..11:
int randrange(int low,int high)
{
return rand()%(high-low+1)+low;
}
Your program has a number of flaws, one of which is the range of random numbers that the randrange function returns. It's not 1 to 9!
The direct cause of your program (the hanging of the program) is however, that you set check to false, then perform a loop that does nothing (because the first time around, i is 0 and the inner loop with j is never performed), so check will always be false.
Check the other answers for solutions.
Your program is probably looping. It's bit hard to read your code because of your weird indentation, but it looks like there's a logic flaw in your for loop here:
check=false;
do
{
num[i]=randrange(1,9);
for(j=0;j<i;j++)
{
if( num[i]==num[j]) // checks whether number already exists in the array
check=false;
else
check=true;
}
} while(check==false);
You might want to remove the second check=false; line to do what I think you're trying to do.
Okay, you already might have figured out the problem by dasbinkenlight's answer
And in addition to Peter's answer, you can use std::map too to achieve unique random numbers:
std::map<int,int> m;
srand (time (NULL));
for(i=0;i<9;i++){
do{
j=randrange(1,9);
}while(m.find(j)!=m.end());
m[j]; //insert into map, no need for value.
num[i]=j;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
void rnd(vector<int> &v, const int n){
for (size_t i=0;i<=n;++i){
v.push_back(i);
}
random_shuffle(v.begin(), v.end());
}
void PrintVector(const vector<int> &x){
for (size_t i=0;i<x.size(); ++i){
cout<<x[i]<<'\t';
}
}
int main(){
vector<int> a;
rnd(a,10);
PrintVector(a);
}
This code works fine for me to generate an array of random numbers from 1 to 9 without repetition
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
int main(){
srand(time(0));
int arr[10];
for(int i=0; i<9; i++){
arr[i] = i+1;
cout << arr[i] << " ";
}
int j=0;
int temp=0;
cout << "\n\n\n-------------------------\n\n\n";
for(int i=0; i<9; i++){
j = (rand()%8)+1;
temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
for(int i=0; i<9; i++){
cout << arr[i] << " ";
}
}