Finding a repeated element in an array - c++

I have come up with this problem on my own. I am only a beginner and learning C++ currently.
Q. Find all the repeated elements in an array and provide their index number.
I am trying to solve this question using for loops.
#include <iostream>
using namespace std;
void arfn(int var1[],int length){
int x,y;
int store[length];
for(x=0;x<length;x++){
store[x]=var1[x];}
for(int counter=0;counter<length;counter++)
{
cout<<store[counter]<<endl;
for(x=0;x<length;x++) {
for (y=0;y!=x && y<length;y++)
/*By these loops i expect to find index number of repeated elements,
eliminating the case of program showing the same index numbers*/
{
if(store[x]=store[y]) {
cout<<store[x]<<" "<<x<<" "<<y<<" "<<endl;
}
}
}
}
}
int main()
{
int numbers[]={22,33,44,55,55};
int length=5;
arfn(numbers,length);
return 0;
}
I expect to find the output as
55 3 4
but the output is really huge and is nowhere close to the desired output.

I might suggest, that you get acquainted with the STL first, if you are willing to make C++ a power tool for you.
The following program does the job by transforming a vector to a map, which takes care of the indices.
#include <iostream>
#include <vector>
#include <iterator>
#include <map>
void printDuplicates(const std::vector<int>& arr)
{
std::map<int, std::vector<int>> map;
for (auto iter=arr.begin(); iter!=arr.end(); iter++)
{
auto index = std::distance(arr.begin(), iter);
map[*iter].push_back(index);
}
for (auto& iter : map)
{
if (map[iter.first].size()>1)
{
std::cout << iter.first << " ";
for (auto iterIndices : map[iter.first])
{
std::cout << iterIndices << " ";
}
std::cout << std::endl;
}
}
}
int main() {
std::vector<int> arr{ 1,2,5,7,2,8,4,7 };
printDuplicates(arr);
}

You can find many articles on this algorithmic problem
here is one:
Solving Algorithmic Problems: Find a Duplicate in an Array
You should approach this challenge with some questions
What is the expected input size?
What is the required complexity?
Can I use more memory to optimize the complexity?
Is my input sorted or not?
Then you may start with the naive implementation and try to figure
how can it be optimized
For example:
Which parts of my code run more than once
As for using C++, try looking for C++ specifics,
use std::vector or std::array instead of C style arrays
look for STL algorithms which may solve some of your questions

Related

How to get an element (struct) in an array by a value in the struct

Let's say I have this struct containing an integer.
struct Element
{
int number;
Element(int number)
{
this->number = number;
}
};
And I'm gonna create a vector containing many Element structs.
std::vector<Element> array;
Pretend that all the Element structs inside array have been initialized and have their number variable set.
My question is how can I instantly get an element based on the variable number?
It is very possible to do it with a for loop, but I'm currently focusing on optimization and trying to avoid as many for loops as possible.
I want it to be as instant as getting by index:
Element wanted_element = array[wanted_number]
There must be some kind of overloading stuff, but I don't really know what operators or stuff to overload.
Any help is appreciated :)
With comparator overloading implemented, std::find is available to help:
#include <iostream>
#include <vector>
#include <algorithm>
struct Element
{
int number;
Element(int number)
{
this->number = number;
}
bool operator == (Element el)
{
return number == el.number;
}
};
int main()
{
std::vector<Element> array;
std::vector<int> test;
for(int i=0;i<100;i++)
{
auto t = clock();
test.push_back(t);
array.push_back(Element(t));
}
auto valToFind = test[test.size()/2];
std::cout << "value to find: "<<valToFind<<std::endl;
Element toFind(valToFind);
auto it = std::find(array.begin(),array.end(),toFind);
if(it != array.end())
std::cout<<"found:" << it->number <<std::endl;
return 0;
}
The performance on above method depends on the position of the searched value in the array. Non-existing values & last element values will take the highest time while first element will be found quickest.
If you need to optimize searching-time, you can use another data-structure instead of vector. For example, std::map is simple to use here and fast on average (compared to latest elements of vector-version):
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
struct Element
{
int number;
Element(){ number = -1; }
Element(int number)
{
this->number = number;
}
};
int main()
{
std::map<int,Element> mp;
std::vector<int> test;
for(int i=0;i<100;i++)
{
auto t = clock();
test.push_back(t);
mp[t]=Element(t);
}
auto valToFind = test[test.size()/2];
std::cout << "value to find: "<<valToFind<<std::endl;
auto it = mp.find(valToFind);
if(it != mp.end())
std::cout<<"found:" << it->second.number <<std::endl;
return 0;
}
If you have to use vector, you can still use the map near the vector to keep track of its elements the same way above method just with extra memory space & extra deletions/updates on the map whenever vector is altered.
Anything you invent would with success would look like hashing or a tree in the end. std::unordered_map uses hashing while std::map uses red-black tree.
If range of values are very limited, like 0-to-1000 only, then simply saving its index in a second vector would be enough:
vec[number] = indexOfVector;
Element found = array[vec[number]];
If range is full and if you don't want to use any map nor unordered_map, you can still use a direct-mapped caching on the std::find method. On average, simple caching should decrease total time taken on duplicated searches (how often you search same item?).

How to search in a Set of vectors of integers

I am trying to form a set of vectors of integers and on checking if the same solution already exists in the set, I am not getting correct answer.
This is in regards to C++11. I had posted a similar kind of query earlier as well but had not got any meaningful replies.
Why is it that whenever we form a map or set of vectors, is is not able to recognize if I insert a vector which is identical to the one I have already inserted ?
I have been searching for an answer since months. Also, since this behavior is allowed in other languages like Java, there must be a work around this. It would be great if someone can point out why this behavior isn't working the way I expect it to and what should be the probable solution to this.
The code below is a solution to 3Sum problem on Leetcode, but doesn't work because of exactly what I have explained above.
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>result;
unordered_map<int,int>m;
set<vector<int>>res;
bool flag=false;
if(nums.size()<=2)
return result;
vector<int>temp;
for(int i=0;i<nums.size()-1;i++)
{
int comp=-(nums[i]+nums[i+1]);
if(m.find(comp)!=m.end())
{
auto location=m.find(comp);
temp.push_back(comp);
temp.push_back(nums[i]);
temp.push_back(nums[i+1]);
if(res.find(temp)==res.end())
{
res.insert(temp);
result.push_back(temp);
}
temp.clear();
}
else
{
m[nums[i]]=i+1;
m[nums[i+1]]=i+2;
}
}
return result;
}
On giving input as
[0,0,0,0]
Answer should be:
[0,0,0]
Whereas I get :
[[0,0,0], [0,0,0]]
You could use tuples in the set instead of vectors.
#include <tuple>
#include <set>
#include <iostream>
using std::get;
int main(int argc, char* argv[]) {
std::set<std::tuple<int,int,int>> sums;
auto tup1 = std::make_tuple(0, 0, 0);
sums.insert(tup1);
auto tup2 = std::make_tuple(0,0,0);
sums.insert(tup2);
std::cout << sums.size() << std::endl;
for (auto& item : sums) {
std::cout << "(" << get<0>(item) << "," << get<1>(item) << "," << get<2>(item) << ")\n";
}
return 0;
}

C++ - STL - Vector - Why there is no facility to indicate relocation_count in the vector

It is quite surprising that given that reserving size for a vector in anticipation helps improve the performance of the application and
ensures that costly relocations do not occur when it gets filled
to its capacity why there is no facility given to get a relocation_count
at any given time , this may very much help programmer track optimal
size to be allocated to vector in cases where the exact capacity may
need to be determined from average over period of observations as
exact figure may not be known upfront.
To count re-allocations of a std::vector, the std::vector (or at least the write access methods of it) might be wrapped into a helper class.
Sample code:
#include <iostream>
#include <vector>
template <typename VALUE>
struct AllocCounter {
std::vector<VALUE> &vec;
unsigned n;
AllocCounter(std::vector<VALUE> &vec): vec(vec), n(0) { }
void push_back(const VALUE &value)
{
size_t old = vec.capacity();
vec.push_back(value);
n += old != vec.capacity();
}
};
int main()
{
std::vector<int> values;
AllocCounter<int> countAllocs(values);
for (int i = 1; i <= 1024; ++i) {
unsigned nOld = countAllocs.n;
countAllocs.push_back(i);
if (countAllocs.n > nOld) std::cout << 'R';
std::cout << '.';
}
std::cout << '\n'
<< "Number of (re-)allocations: " << countAllocs.n << '\n';
// done
return 0;
}
Output:
R.R.R..R....R........R................R................................R................................................................R................................................................................................................................R................................................................................................................................................................................................................................................................R................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Number of (re-)allocations: 11
Live Demo on coliru
This sample is rather a proof of concept as it doesn't consider std::vector::emplace(), std::vector::resize(), etc.
Btw. if std::vector::push_back() is called directly the counting is by-passed (and may "overlook" re-allocations).
Using a custom allocator could solve this limitation.

How do you make a vector that displays 24,60, and 1?

Simple problem that I know I should know. All I want to do is display a vector when I give it those parameters, then I have to display it in reverse order.
Have a look at cplusplus.com first.
The following code compiles in C++98.
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char** argv) {
vector<int> myvec;
myvec.push_back(1); myvec.push_back(2); myvec.push_back(3);
for( vector<int>::iterator it = myvec.begin(); it!=myvec.end(); ++it){
cout<<*it<<" ";
}
cout<<"\nRverse Order "<<endl;
for( vector<int>::reverse_iterator it = myvec.rbegin(); it!=myvec.rend(); ++it){
cout<<*it<<" ";
}
return 0;
}
There are a number of ways to do this
Using loops and indices and printing to the screen.
Using iterators.
However, as you realize that in both cases you're outputting to the screen, it may be a better idea to use a stream to encapsulate this behavior by using an overloaded insertion operator (in addition to one of those paradigms):
std::ostream& operator<<(std::ostream& out, const vector<int>& v) {
for (std::vector<int>::const_reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
out << *it << " ";//you can use a newline here if you wanted every element on a new line
}
return out;
}
Usage:
vector<int> vec;
//fill `vec` with data
//...
std::cout << vec << std::endl;
WARNING
While this is a sensible idea as it is arguably more object-oriented, it abstracts away the meaning of the extraction operator as it violates the principle of least surprise. However, if this behavior is intended and consistent, then depending on your usage, it is perfectly fine.

Use for_each or accumulate to calculate frequencies

I've been playing with a simple example using C++11 and some standard algorithms, and I'm not sure whether to use std::accumulate or std::for_each. The problem is to count letters in a word, so, for example, for an input of "abracadabra", you get
'a' => 5
'b' => 2
'c' => 1
'd' => 1
'r' => 2
My first cut was to use std::accumulate. The reason this seemed natural is that we're really accumulating a value (a set of frequencies). Also I've been doing some functional programming recently and accumulate seemed to be the natural translation of folding a list.
vector<int> charsInWord(const string& text)
{
return
std::accumulate(text.begin(), text.end(), vector<int>(256),
[] (const vector<int>&v, char c)
{
vector<int> v2(v);
v2[c]++;
return v2;
} );
}
However this solution seemed rather cumbersome and took a little while to get right. Moreover, even with the new move semantics I couldn't quite convince myself that there wouldn't be any unnecessary copying.
So I went for for_each instead.
vector<int> charsInWord2(const string& text)
{
vector<int> charCounts(256);
std::for_each(text.begin(), text.end(),
[&] (char c)
{
charCounts[c]++;
} );
return charCounts;
}
This is probably easier to write and understand, and I certainly feel happier about its efficiency (although I miss the declarative, functional style of accumulate).
Is there any good reason to prefer one over the other in examples like these? From the comments and answers so far, it seems like if the value I am accumulating is non-trivial, say an stl container rather than an int, I should always prefer for_each, even when I am really "accumulating".
For the sake of completeness, the rest of the code to get this to compile and test is below
#include <string>
#include <vector>
#include <numeric> // accumulate
#include <algorithm> // for_each
using std::string;
using std::vector;
#include <iostream>
// ... insert code above ...
int main(int argc, char* argv[])
{
const vector<int> charCounts = charsInWord("abracadabra");
for(size_t c=0; c<charCounts.size(); ++c) {
const int count = charCounts[c];
if (count > 0) {
std::cout << "'" << static_cast<char>(c) << "'" << " => " << count << "\n";
}
}
return 0;
}
Personally I would not have written the accumulate like that:
vector<int> charsInWord(const string& text)
{
std::vector<int> result(256); // One version never copied.
int count = std::accumulate(text.begin(), text.end(), 0,
[&result] (int count, char c)
// ^^^^^^^^^ capture
{
result[c]++;
return count+1;
} );
// Might use count in the log file.
return result;
}
But If I am doing that it seems just as easy to use for_each()
vector<int> charsInWord2(const string& text)
{
vector<int> result(256);
std::for_each(text.begin(), text.end(),
[&result] (char c)
{
result[c]++;
} );
return result;
}
I don't see anything wrong with the for_each version.
But why not go with a simple for() loop?
vector<int> charsInWord2(const string& text)
{
vector<int> result(256);
for(char c : text) {result[c]++;}
return result;
}
There was some discussion about using std::map in the comments (and then in some deleted questions). Just to capture that here and expand.
We could have used std::map<char,int> instead of vector<int>. The difference are:
From: #Dave std::map has O(ln(n)) lookup time while vector is O(1). So there is a performance consideration. Note also that the fixed cost for map will be higher than vector. Though this is small but worth noting.
From: #Dave std::vector has a fixed size of approx 256*4 (1024), while map has a size of approx 12*number of unique characters (min 12 max 3072). So no real space consideration in modern machine. But may be worth optimizing on phones and such.
From: #POW The third point is the std::map makes printing the result much easier as you do not need to check for empty values.
Vector print
for(size_t c=0; c<charCounts.size(); ++c) {
if (count > 0) {
std::cout << "'" << static_cast<char>(c) << "' => " << charCounts[c] << "\n";
}
}
Map Print
for(auto loop: charCounts) {
std::cout << "'" << loop.first << "' => " << loop.second << "\n";
}