So I have an array as :
arr[] = {5, 2,4,2,3,5,1};
How can I insert them in this order with the number of times they occur in unordered_map?
#include<bits/stdc++.h>
using namespace std;
void three_freq(int arr[], int n){
unordered_map<int, int> m;
for(int i=0;i<n;i++){
m[arr[i]]++;
}
for(auto itr = m.begin(); itr != m.end(); itr++){
cout<<itr->first<<":"<<itr->second<<"\n";
}
}
int main(){
int arr[] = {5, 2,4,2,3,5,1};
int n = sizeof(arr)/ sizeof(arr[0]);
three_freq(arr, n);
return 0;
}
Using the code above I am getting output as :
1:1
3:1
4:1
5:2
2:2
But I want the output to be in same order as the element occur in array.
Example:
5:2
2:2
4:1
3:1
1:1
If you don't care about efficiency (that much), then you can just change the for loop which is printing the output.
for(int i=0; m.size(); i++) {
auto it = m.find(arr[i]);
if (it != m.end()) {
cout<<arr[i]<<":"<<it->second<<"\n";
m.erase(it);
}
}
The quite efficient way is traversing the original array and resetting the counters after print.
for (int i = 0; i < n; ++i) {
if (m[a[i]]) != 0) {
std::cout <<arr[i] << ":" << m[a[i]] << std::endl;
m[a[i]] = 0;
}
}
You need unordered_map to do the counting efficiently, so keep that.
When printing out according to the order in another container, it makes sense to simply iterate over that other container for your output loop.
(Note that this is a completely separate operation, so it could have been a different function.)
// loop over the original array (recommend std::vector)
// exit early if done (stole from fadedreamz)
for (int index = 0; !m.empty(); ++index) {
int number = arr[index];
// check to see if we need to print this number
// use contains if you have c++20
if (m.count(number)) {
std::cout << number << ":" << m[number] << std::endl;
m.erase(number); // print only once by deleting the entry
}
}
Related
I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}
Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.
It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
I am trying to remove the duplicate elements in a sorted vector such that each element appears only once.
My code:
#include <iostream>
#include <vector>
using namespace std;
void removeDuplicates(vector<int> &nums)
{
vector<int>::iterator it;
unsigned int j = 1;
while(j < nums.size()-1)
{
if(nums.at(j) == nums.at(j-1))
{
it = nums.begin()+j;
nums.erase(it);
--j; // for every removal, correct the index
}
j += 1; // increment the index
}
}
int main ()
{
vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++)
{
cout << vect[i] << " ";
}
cout << endl;
return 0;
}
When I run the code, the output is
The vector unique elements are: 0 1 2 3 4
The question gives the following instruction:
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
In my code, the Big O time complexity is O(n).
How can I remove the duplicates in-place with an extra memory of O(1)?
How can remove the duplicates in-place with a time complexity of O(1)?
You can't. Even with the vector sorted, you simply must compare every single element to know whether it is unique or not. O(N) is optimal.
However, O(1) time complexity wasn't required by the task either:
... with O(1) extra memory.
There was no mention of time complexity constraint - only space complexity.
The simplest way to get rid of duplicates is to use what's already available in the standard library:
nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
You can implement it in place (no extra memory) with a complexity O(n) by simply using two indices, one for reading the elements and one for writing.
#include <iostream>
#include <vector>
void removeDuplicates(std::vector<int> &nums)
{
unsigned int j = 1;
for (unsigned int i = 1; i < nums.size(); i++)
{
if(nums.at(i) != nums.at(i-1))
{
nums.at(j++) = nums.at(i);
}
}
nums.resize(j);
}
int main ()
{
std::vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
std::cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++) {
std::cout << vect[i] << " ";
}
std::cout << "\n";
return 0;
}
I want to declare a 2d array of 500 * 500 size(for example).
Is a vector of arrays the best way to go?
I can't seem to print the array and every other code declares the iterator of vector type but i want to do it using int type.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<list>
#include<stack>
#define white 0
#define black 1
using namespace std;
void print(vector< list<int> > adjList)
{
for(int i = 0; i<adjList.size(); i++)
{
for(int j = adjList[i].begin(); j != adjList[i].end(); j++)
{
cout<<j<<" "; //adjList[i][j] doesnt work
}
cout<<endl;
}
}
int main()
{
int n,m;
cin>>n>>m;
vector< list<int> > adjList;
for(int i = 0; i<m ; i++)
{
int u,v;
cin>>u>>v;
adjList[u].push_back(v);
adjList[v].push_back(u);
}
print(adjList);
}
You can't iterate through a list with an integer, but you can declare j as an iterator (std::list<int>::iterator j = adjList[i].begin();) and use the asterisk like in pointers to get the element that an iterator is pointing at like this: cout << *j << ' ';. If you want to print a vector of arrays, just do it like how you would normally print a 2D array. The std::list container implements a linked list and is very different from containers that store elements in contiguous memory such as arrays and std::vector, which is likely not what you want here since it doesn't have random access.
By the way, if you want to pass large containers like vectors to a function like print() that does not need to modify the vector, you should use a constant reference instead of copying the vector. There is something called a range based for loop in C++11 that can iterate through things like vectors without you having to worry about things like iterators, and a std::set is probably more suited for implementing an adjacency list since it allows for checking if two vertices are adjacent with logarithmic complexity.
Lastly, in your input loop, you used adjList[u] when that element does not exist yet since adjList is empty. You should add a line adjList.resize(n) after you input n to create the empty sets or just declare adjList after you input n and use n as the constructor argument like this to tell the constructor to initialize adjList with a bunch of empty sets: vector<set<int>> adjList(n);.
Since it looks like you are doing a competitive programming problem, I would advise you to convert the input to zero indexing before doing any processing.
My code using range based for loops:
#include <iostream>
#include <vector>
#include <set>
void print(const std::vector<std::set<int>> &adjList)//pass by const reference
{
for(std::size_t i = 0; i < adjList.size(); i++)
{
std::cout << i << ": ";
for(auto &j : adjList[i])//range based for loop to iterate through adjList[i] and use the reference j to refer to each element
{
std::cout << j << ' ';
}
std::cout << '\n';
}
}
int main()
{
int n, m;
std::cin >> n >> m;
std::vector<std::set<int>> adjList(n); //adjList starts with n empty sets
for(int i = 0; i < m; i++)
{
int u, v;
std::cin >> u >> v;
adjList[u].insert(v);
adjList[v].insert(u);
}
print(adjList);
}
The problem is you have a vector of lists, but list does not define operator[], which you then try to use to access the elements of it.
Since you say you want a fixed array 500 x 500, you don't want a vector of lists anyway, because lists are not a fixed length.
So try a vector of vectors, for example.
You cannot use int to iterate over the list.
List in C++ are implemented using doubly linked list in which they uses pointers to access the next/previous elements.
The type I would recommend you to use is list<int>::iterator as it is a standard way to iterate over a list.
There are some other ways to do it also. For example:
for(auto x : adjList[i]){
cout << x << " "; // Do something
// Only valid in C++11 or newer.
}
Another example:
for(auto j = adjList[i].begin(); j != adjList[i].end(); j++){
cout << *j << " "; // Do something with j (iterator) or *j (value).
// Only valid in C++11 or newer.
}
For the classic C++ example would be:
for(list<int>::iterator it = adjlist[i].begin(); it != adjlist[i].end(): it++){
cout << *it << " ";
}
you can use range based for loop in your print function like below:
void print(vector< list<int> > adjList)
{
for(auto i : adjList)
{
for(auto j: i)
{
cout << j << " ";
}
}
}
however you will get seg fault when you run your code. The main function below should be self explanatory
int main()
{
int n,m;
cin>>n>>m;
vector< list<int> > adjList;
cout << "entered value : n" << n <<" m : "<<m <<endl;
for(int i = 0; i<m ; i++)
{
int u,v;
cin>>u>>v;
adjList.push_back({v});
adjList.push_back({u});
}
print(adjList);
}
Note that a std::list is not an array and does not support indexing with operator[]. You could simply replace the use of list throughout your program with vector instead, and print() would look something like
void print(vector< vector<int> > adjList)
{
for (int i = 0; i < adjList.size(); i++)
{
for (int j = 0; j < adjList[i].size(); j++)
{
cout << adjList[i][j] << ' ';
}
cout << endl;
}
}
I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}
This program reads strings of numbers from a txt file, converts them to integers, stores them in a vector, and then tries to output them in an organized fashion like so....
If txt file says:
7 5 5 7 3 117 5
The program outputs:
3
5 3
7 2
117
so if the number occurs more than once it outputs how many times that happens. Here is the code so far.
#include "std_lib_facilities.h"
int str_to_int(string& s)
{
stringstream ss(s);
int num;
ss >> num;
return num;
}
int main()
{
cout << "Enter file name.\n";
string file;
cin >> file;
ifstream f(file.c_str(), ios::in);
string num;
vector<int> numbers;
while(f>>num)
{
int number = str_to_int(num);
numbers.push_back(number);
}
sort(numbers.begin(), numbers.end());
for(int i = 0; i < numbers.size(); ++i)
{
if(i = 0 && numbers[i]!= numbers[i+1]) cout << numbers[i] << endl;
if(i!=0 && numbers[i]!= numbers[i-1])
{
cout << numbers[i] << '\t' << counter << endl;
counter = 0;
}
else ++counter;
}
}
Edit: Program is getting stuck. Looking for an infinite loop right now.
You could use a map of numbers to counters:
typedef map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
... then iterate over the map to print results.
EDIT:
As suggested by lazypython: if you have the TR1 extensions [wikipedia.org] available, unordered_map should have better performance...
typedef std::tr1::unordered_map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
How about using a map, where the key is the number you're tracking and the value is the number of occurrences?
If you must use a vector, you've already got it sorted. So just keep track of the number you previously saw. If it is the same as the current number, increment the counter. Every time the number changes: print out the current number and the count, reset the count, set the last_seen number to the new number.
Using a map is the practical solution. What you should do is to solve this problem :)
This is called frequency counter. So, you have a sorted vector and all what you have to do is to count successive equal numbers. In other words, you have to check each number with its successor.
for(size_t i = 0; i < numbers.size(); i++)
{
size_t count = 1;
size_t limit = numbers.size() - 1;
while(i < limit && numbers[i] == numbers[i+1])
{
count++;
i++;
}
std::cout << numbers[i] << "\t" << count << std::endl;
}
This program reads strings of numbers
from a txt file, converts them to
integers, stores them in a vector, and
then tries to output them in an
organized fashion like so....(emphasis added)
What is the point of this storage step? If you are reading the numbers from a file, then you already have them in order, ready to be processed (counted) one at time, as you encounter them.
However, I would need a way for it to know when it sees a new number.
I advise you to have a look at std::set or std::map. I expect either of these containers would do what you're looking for.
Std::count() fits the bill nicely.
std::vector<int>::const_iterator cur = numbers.begin();
std::vector<int>::const_iterator last = numbers.end();
while (cur != last) {
unsigned cnt = std::count(cur, last, *cur);
std::cout << *cur;
if (cnt != 1) {
std::cout << " " << c;
}
std::cout << std::endl;
int saved = *cur;
while (*cur == saved) {
++cur;
}
}
Of course there are a bunch of other algorithms out there that will do the same job. Play with things like std::equal_range() in conjunction with std::distance() will do the job just as nicely.
That was fun:
#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
struct IncrementMap
{
IncrementMap(std::map<int,int>& m): m_map(m) {}
void operator()(int val) const
{
++m_map[val];
}
std::map<int,int>& m_map;
};
struct SpecialPrint
{
SpecialPrint(std::ostream& s): m_str(s) {}
void operator()(std::map<int,int>::value_type const& value) const
{
m_str << value.first;
if (value.second != 1)
{
m_str << "\t" << value.second;
}
m_str << "\n";
}
std::ostream& m_str;
};
int main()
{
std::fstream x("Plop");
std::map<int,int> data;
std::for_each( std::istream_iterator<int>(x),
std::istream_iterator<int>(),
IncrementMap(data)
);
std::for_each( data.begin(),
data.end(),
SpecialPrint(std::cout)
);
}