I have 2 arrays in which arr1 stores a number (the salary) and arr2 stores a string (the employee's name). Since the two arrays are linked, I cannot change the order of arr1, or sort it. I am looking for a more efficient way to solve the problem which is to find if there are any duplicates in the array. It might be more than one duplicate, but if no are found it should print "no duplicates found".
int count = 0;
for (int i = 0;i<arr_size ;i++)
{
for (int j = 0; j < arr_size && i != j; j++)
{
if (arr[i] == arr[j])
{
cout << arr2[i] << " " << arr1[i] << endl;
cout << arr2[j] << " " << arr1[j] << endl;
count ++;
}
}
}
if (count == 0)
{
cout << "No employee have same salaries"<<endl;
}
I don't want to use such an inefficient way to solve the problem. Is there any better suggestion? Thanks for the help :)
And the question also requires me to print out all the duplicated employee and salaries pair
You can use an unordered_set which has an average constant time insertion and retrieval:
#include <unordered_set>
// ...set up arr
int count = 0;
std::unordered_set<int> salaries;
for (int i = 0; i < arr_size; i ++) {
if (salaries.count(arr[i]) > 0) {
// it's a duplicate
}
salaries.insert(arr[i]);
}
// do more stuff
Create a Haspmap using unordered_map and store salaries and index of the salary .
Now if the same salary exist then increase count
You can reduce the time complexity of the algorithm to O(n) by using unordered_set on the expense of using additional space.
#include<unordered_set>
int main(){
// Initialise your arrays
unordered_set<string> unique;
bool flag = false;
for(int i=0;i<arr_size;i++){
// Since unordered_set does not support pair out of the box, we will convert the pair to string and use as a key
string key = to_string(arr1[i]) + arr2[i];
// Check if key exists in set
if(unique.find(key)!=unique.end())
unique.push(key);
else{
// mark that duplicate found
flag = true;
// Print the duplicate
cout<<"Duplicate: "+to_string(arr1[i])+"-"+arr2[i]<<endl;
}
}
if(!flag){
cout<<"No duplicates found"<<endl;
} else cout<<"Duplicates found"<<endl;
return 0;
}
Related
I would like to know if I can perform operations on some numbers straight in the file without
the need to read them. I wrote this code to check if a file is sorted but I had to read them
first into a vector and then check if the vector is sorted or not but then I figured that this
code might be inefficient since I had to make few extra steps. this is the code:
// method to check if the numbers are already sorted:
bool number_sorted(vector <int> vector){
bool is_sorted = true;
for(int i = 0; i < vector.size(); i++){
for(int j = i + 1; j < vector.size(); j++){
if(vector[i] > vector[j]){
is_sorted = false;
cout << vector[i] << " and " << vector[j] << " are in the wrong order" << endl;
}
}
}
return is_sorted;
}
// method to sort the numbers:
vector <int> sort(vector <int> vector){
for(int i = 0; i < vector.size(); i++){
for(int j = i + 1; j < vector.size(); j++){
if(vector[i] > vector[j]){
int temp = vector[i];
vector[i] = vector[j];
vector[j] = temp;
}
}
}
return vector;
}
// Main methdod:
int main(){
vector <int> list;
fstream fs;
fs.open("/Users/brah79/Downloads/skola/c++/inlämningsuppgiter/number1.txt");
bool is_sorted = number_sorted(list);
if(is_sorted){
cout << "the list of numbers is sorted" << endl;
}
else{
sort(list);
}
as you can see everything is performed on a vector first but I want to make the check and the
sorting straight on the file. Hope I made myself clear
You have to read file there is not other way.
But you do not have to keep everything in vector
bool areIntsInStreamSorted(std::istream& in)
{
return std::is_sorted(std::istream_iterator<int>{in}, {}) && in.eof();
}
bool areIntsInFileSorted(std::filesystem::path p)
{
std::ifstream in{p};
return areIntsInStreamSorted(in);
}
https://en.cppreference.com/w/cpp/algorithm/is_sorted
https://en.cppreference.com/w/cpp/iterator/istream_iterator
live demo
Lets look at your implementation:
bool number_sorted(vector <int> vector){
bool is_sorted = true;
for(int i = 0; i < vector.size(); i++){
for(int j = i + 1; j < vector.size(); j++){
if(vector[i] > vector[j]){
is_sorted = false;
cout << vector[i] << " and " << vector[j] << " are in the wrong order" << endl;
}
}
}
return is_sorted;
}
You consider every element vector[i] and then check for all j > i that vector[i] is not greater than vector[j]. If it is, the vector is not sorted. If you you encounter no such pair of elements vector[i] and vector[j] then the vector is sorted.
If this was the way to check if a sequence of numbers is sorted, then yes, then you need all numbers in memory.
However, it is not. It is much simpler. In a sequence that is not sorted, there is at least one index i where
vector[i] > vector[i+1]
and thats it. If any pair of adjacent elements is sorted, then the whole sequence is sorted too.
You only ever have to compare one number with the next. You do not need to store all elements to check if they are sorted. When you read from the file, remember the previous number, read the next, and check if the next is bigger or equal the previous one.
I am a beginner in C++ trying to figure out how I could solve the following exercise:
Given an array of whole numbers, count how many times one element is present in the array. After that, copy the array indexes to another array and print them. In other words, apart from printing the amount of times one chosen number is present in the array, I need to print the indexes of that chosen number from a second array (by copying them from the first array to the second).
Example:
int myvect [ ] = {10, 42, 20, 10, 13, 20}
Assuming I choose the number 10 using the keyboard. The program will have to output the following:
The chosen element is present: 2 times
The chosen element is present in the following indexes: 0, 3
I don't have problems outputting how many times one element is present. I just added a counter and it works perfectly. My problem is i don't know how to select those specific indexes, copy them to another array to finally print them.
Here is my code:
#include <iostream>
#define max 20
using namespace std;
int main()
{
int vett[max],n,i,num,app=0,cont=0,pos[50];
bool flag;
cout<<"inserisci un numero massimo elementi del vettore:";
cin>>n;
cout<<endl;
flag=false;
for (i=0; i<n; i++) {
cout<<"inserisci elementi del vettore:";
cin>>vett[i];
}
cout<<"inserisci elemento da trovare: ";
cin>>num;
cout<<endl;
i=0;
for (i=0; i<n; i++) {
if(vett[i]==num) {
cout<<"trovato"<<endl;
flag=true;
app=i;
cont++;
}
}
if(flag==true) {
cout<<"elemento trovato"<<endl;
if(cont>1) {
cout<<"l'elemento e' stato trovato "<< cont<<" volte"<<endl;
}
else if(cont==1) {
cout<<"l'elemento e' stato trovato "<< cont<<" volta"<<endl;
}
cout<<"Posizioni Salvate: "<<vett[i]<<endl;
}
else {
cout<<"elemento non trovato"<<endl;
}
system("pause");
return 0;
}
As you can see, I did define a second array in the beginning. I don't know how to use it to solve the problem
Any help will be appreciated. Thank you very much
I usually make modifications to the OP's code as a part of my answer, but I cannot understand your language in the code. So, I will give you the basic algorithm to help you solve your problem keeping the structure of your attempted code intact.
Let the array of required indexes be int indexes[max];
Let k be the current index of indexes to keep track of the insertion
Each time you find the element in your i loop, insert the value of i into indexes[k] and increment the value of k
Demo:
int indexes[max], k = 0;
for (int i = 0; i < n; ++i)
{
if (vett[i] == num)
{
// Do the Part 1 of your task
// This line will help you achieve the Part 2:
indexes[k++] = i;
}
}
You could use std::find
An example:
std::array<int, 5> data{10, 2, 3, 4, 10};
std::vector<int> indices;
int num = 10;
auto it = data.begin();
while ((it = std::find(it, data.end(), num))!= data.end())
{
indices.push_back(std::distance(data.begin(), it));
it++;
}
indices then contains the indices of the elements that match your search criterion.
In your loop:
for (i=0; i<n; i++) {
if(vett[i]==num) {
cout<<"trovato"<<endl;
flag=true;
app=i;
cont++;
}
}
You are trying to test if number at index i is your desired number. Well, what about storing that i index into another array everytime the condition is true.
// create array with the same size as input array
int found_indexes[max];
size_t current_position = 0;
// now your loop
for (i=0; i<n; i++) {
if(vett[i]==num) {
cout<<"trovato"<<endl;
flag=true;
app=i;
cont++;
// save index at current position and advance by one after saving
found_indexes[current_position++] = i;
}
}
// at the end print all indexes from array
// this is done by printing all values until we meet with current_position index
if (current_position == 0)
cout << "No indexes found.\n";
else
{
// Printing spaces somewhat nicely.
cout << found_indexes[0];
for(size_t i = 1; i < current_position; i++)
cout << ' ' << found_indexes[i];
}
I think you are trying to do that
#include <iostream>
#include <stdlib.h>
#define max 20
using namespace std;
int main()
{
int vett[max],n,i,num,cont=0,pos[50];
bool flag;
cout<<"Enter how many numbers:";
cin>>n;
cout<<endl;
flag=false;
for (i=0; i<n; i++)
{
cout<<"Enter "<<i+1<<" Element:";
cin>>vett[i];
}
cout<<"\nEnter what to find: ";
cin>>num;
cout<<endl;
for (i=0; i<n; i++)
{
if(vett[i]==num)
{
flag=true;
pos[cont++]=i;
}
}
if(flag==true)
{
cout<<"The chosen element is present:"<<cont<<" times"<<endl;
cout<<"The chosen element is present in the following indexes:";
for(i=0;i<cont;i++)
cout<<pos[i]<<","; //it prints a number followed by a comma.
cout<<endl;
}
else
cout<<"No Element"<<endl;
system("pause");
return 0;
}
Output:
Enter how many numbers:6
Enter 1 Element:10
Enter 2 Element:42
Enter 3 Element:20
Enter 4 Element:10
Enter 5 Element:13
Enter 6 Element:20
Enter what to find: 10
The chosen element is present:2 times
The chosen element is present in the following indexes:0,3,
Press any key to continue . . .
Process returned 0 (0x0) execution time : 29.955 s
Press any key to continue.
Edit:
if you did not want comma after last element use this
for(i=0;i<cont;i++)
{
cout<<pos[i];
if((i+1)!=cont)
cout<<",";
}
I think that the appropriate data structure here is std::map<int, std::set<int> > which is the hash map representing the value mapped to the set of indices where this value is present. The size of set tells you the number of occurrences of the particular value. Simple implementation might look like this:
std::map<int, std::set<int> > values_to_indices;
for (int i = 0; i < input_array.size(); i++)
{
values_to_indices[input_array[i]].insert(i); // we can use operator[] because when element is not yet in the map, std::set will be default constructed
}
for (auto elem : values_to_indices)
{
std::cout << "element: " << elem.first << " is repeated " << elem.second.size() << " times\n";
// here you can also print std set of indices of that element
}
This doc explains that using operator[] on the map constructs the element if it was not present before. The values in the set are guaranteed to be unique because we iterate once from 0 to input array size.
=== EDIT ===
As suggested in the comment, instead of int you might use size_t as a type representing indices:
std::map<int, std::set<size_t> > values_to_indices;
for (size_t i = 0; i < input_array.size(); i++)
{
values_to_indices[input_array[i]].insert(i);
}
Just be aware of unsigned integer underflow if later you plan to do some things with that indices.
I'm trying to use a bubble sort to sort an array of 10 numbers. The program asks for 10 numbers from the user then outputs the unsorted array. This part works fine. It then runs a bubble sort and outputs the sorted array. In my tests I only entered positive integers, however the first value in the sorted array is always a really small number expressed like "2.6812368e-317" or something similar. The rest of the values in the array then appear after that number sorted as they should be. After the sorted array displays Windows then comes up with an error saying the program has stopped working.
My code is as follows:
int main(int argc, char** argv) {
double arrSort[10];// declare array to store numbers to be sorted
cout << "Please enter 10 numbers to be sorted" << endl;
// ask for values from user and input them in array
for (int i = 0; i < 10; i++)
{
cin >> arrSort[i];
}
// display unsorted array
cout << "Unsorted Array: " << endl;
for (int i = 0; i < 10; i++)
{
if (i < 9)
cout << arrSort[i] << ", ";
else
cout << arrSort[i] << endl;
}
bool changed = true; // variable to store whether a change has been made
double temp; // variable to temporarily store a value while swapping
//start looping the array
do
{
changed = false; // change to false so that if no changes are made to array the loop exits
for (int i = 0; i < 10; i++) // start loop within array to check values
{
if (arrSort[i] > arrSort[i + 1]) // check if current index is greater than next index
{
// swap values
temp = arrSort[i]; // store current index in temp variable
arrSort[i] = arrSort[i + 1]; // assign next index to current index
arrSort[i + 1] = temp; // assign temp value to next index
changed = true; // set changed to true to run another loop
}
}
}while (changed); // if array was changed loop through again, if not changed exit loop
// output results of sorted array
cout << "Sorted Array: " << endl;
for (int i = 0; i < 10; i++)
{
if (i < 9)
cout << arrSort[i] << ", ";
else
cout << arrSort[i] << endl;
}
return 0;
}
Here is a screenshot of a test run of the program:
Sorted Array output
for (int i = 0; i < 10; i++) // <-- here's problem.
{
if (arrSort[i] > arrSort[i + 1])
{
// swap values
}
}
i variable should be less than 9 not 10. As you can see in if statement you are checking arrSort[i + 1], so in last element you are checking number which is out of your table range (arrSort[10] doesn't exist). I'm not able to check it right now, but I guess it's the problem.
I think the problem is here:
if (arrSort[i] > arrSort[i + 1])
When
i=9
Your array have 10 elements and you try to compare
arrSort[9] > arrSort[9+1]
And
arrSort[10]
Does not exist
I'm using bubble sort to sort numbers in an array in order from lowest to highest. But there are some numbers which are the same, but I don't need them to be printed twice. So how do I check whether it was already printed and not to repeat the action?
The Bubble sort:
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
}
}
Since number are already sorted when you are printing it, you can store the last printed number and compare against this before printing.
Something like:
std::cout << m[0] << std::endl;
int last_print = m[0];
for(int i = 1; i < n; ++i)
{
if(m[i] != last_print)
{
std::cout << m[i] << std::endl;
last_print = m[i];
}
}
filter duplicate out when printing (assuming m being int[])
int last = 0;
for(int i=0;i<n;i++){
int num = m[i];
if (i == 0 || last != num) {
// print num;
}
last = num;
}
or this way if you don't like too much vars
for(int i=0;i<n;i++){
if (i == 0 || m[i - 1] != [i]) {
// print m[i];
}
}
Alternatively you could remove duplicates on sort
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;){
if (m[i]==m[j]) { // remove
m [j] = m [n - 1]; // replace with last
n --; // cut last
} else {
if(m[i]>m[j]){
temp=m[i];
m[i]=m[j];
m[j]=temp;
}
j ++;
}
}
}
You can add the number to a std::set as soon as you print it, and check all numbers if they are in the set before printing them.
EDIT: I missed the restriction that the numbers are sorted. In that case, a set is overkill and less efficient than just keeping track of the last number printed, and only printing numbers that are different from it afterwards.
I'm having an issue in which a function that in theory should remove all duplicate values from an array doesn't work. Here's how it works:
I have two arrays, and then I populate them with random numbers
between 0 and 50 inclusive.
I sort the array values in order using a sort function
I then run my dedupe function
I sort the array values in order again
I then output the values in both arrays
The problem is, the loop in the dedupe function is ran 19 times regardless of how many duplicate entries it finds, which is extremely strange. Also, it still gives duplicates.
Any ideas? Thanks!
int* dedupe(int array[ARRAY_SIZE]) //remove duplicate array values and replace with new values.
{ bool dupe = false;
while(dupe!=true)
{
for(int j=0; j<ARRAY_SIZE; j++)
{ if(array[j] == array[j+1])
{ array[j] = rand();
array[j] = array[j] % 51;
dupe = false;
}
else { dupe = true; // the cout part is for debugging
cout << dupe << endl; }
}
} return array;
}
int main()
{
int a[9], b[9];
srand(time(0));
populate(b);
populate(a);
sort(a,ARRAY_SIZE);
sort(b,ARRAY_SIZE);
dedupe(a);
dedupe(b);
sort(a,ARRAY_SIZE);
sort(b,ARRAY_SIZE);
for(int i=0; i<10; i++)
{ cout << "a[" << i << "] = " << a[i] << "\t\t" << "b[" << i << "] = " << b[i] << endl; }
return 0;
}
Nothing suggested so far has solved the problem. Does anyone know of a solution?
You're not returning from inside the for loop... so it should run exactly ARRAY_SIZE times each time.
The problem that you want to solve and the algorithm that you provided do not really match. You do not really want to remove the duplicates, but rather guarantee that all the elements in the array are different, the difference being that by removing duplicates the number of elements in the array would be less than the size of the array, but you want a full array.
I don't know what the perfect solution would be (algorithmically), but one simple answer would be creating an array of all the values in the valid range (since the range is small), shuffling it and then picking up the first N elements. Think of this as using cards to pick the values.
const int array_size = 9;
void create_array( int (&array)[array_size] ) {
const int max_value = 51;
int range[max_value];
for ( int i = 0; i < max_value; ++i ) {
range[i] = i;
}
std::random_shuffle( range, range+max_value );
std::copy_n( range, array_size, array );
}
This is not the most efficient approach, but it is simple, and with a small number of elements there should not be any performance issues. A more complex approach would be to initialize the array with the random elements in the range, sort and remove duplicates (actually remove, which means that the array will not be full at the end) and then continue generating numbers and checking whether they are new against the previously generated numbers.
Simplest approach is just comparing with every other value which is linear time but on an array of 9 elements linear time is small enough not to matter.
you are doing it wrong at
array[j] = rand();
array[j] = array[j] % 51
It will always have 1 to ARRAY SIZE!!