I was solving one problem on leetcode problem - Find K Closest Elements.
Here is my IDE code : ide.geeksforgeeks
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
std::vector<int> findClosestElements(std::vector<int>& arr, int k, int x)
{
std::vector<int> res;
// min heap
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
std::greater<std::pair<int, int>>> pq;
std::cout << "Debug queue : \n";
for (auto it : arr)
{
int closest = abs(it - x);
pq.push(std::make_pair(closest, it));
//std::cout << closest << " : " << it << "\n";
if (pq.size() > k)
{
pq.pop();
}
}
std::cout << "\nIterating queue : \n";
while(!pq.empty())
{
res.push_back(pq.top().second);
std::cout << pq.top().first << " : " << pq.top().second << "\n";
pq.pop();
}
std::sort(res.begin(), res.end());
return res;
}
int main()
{
std::vector<int> arr = {1,2,3,4,5};
auto res = findClosestElements(arr, 4, 3);
return 0;
}
While I was iterating the queue, I can not see the minimum number : 0 : 3 which should be the top element of priority_queue. Can anyone please suggest?
Max heaps solves the problem.
vector<int> findClosestElements(vector<int>& arr, int k, int x)
{
std::vector<int> res;
std::priority_queue<std::pair<int, int>> pq;
for (auto it : arr)
{
int closest = abs(it - x);
//std::cout << closest << " : " << it << "\n";
pq.push(std::make_pair(closest, it));
if (pq.size() > k)
{
pq.pop();
}
}
//std::cout << "\nDebug queue : \n";
while(!pq.empty())
{
res.push_back(pq.top().second);
//std::cout << pq.top().first << " : " << pq.top().second << "\n";
pq.pop();
}
std::sort(res.begin(), res.end());
return res;
}
Related
I am trying to loop through an unordered_map, to find if any of its VALUES is greater than 2. But this syntax is wrong
unordered_map<int, int> mp;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
for (int i = 0; i < mp.size(); i++ ) {
cout << mp[i].second << " " << endl; //mp[i].second is wrong syntax
if (mp[i].second > 2) {
cout << "WRONG";
x = false;
break;
}
}
how can I do this?
It seems that you assumed(incorrectly) that mp[i] is std::pair<int, int> when in fact mp[i] gives you the mapped value which is of type int in your example. This can be seen from std::map::operator[]:
T& operator[]( Key&& key ); (2)
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
(emphasis mine)
Method 1
Since you don't want to use auto, you can explicitly write the type std::pair<int, int> in the range-based for loop as shown below:
//---------vvvvvvvvvvvvvvvvvvvvvvvv--------------------->not using auto here as you want
for (const std::pair<const int, int> &pair_elem: mp) {
cout << pair_elem.second << " " << endl;
if (pair_elem.second > 2) {
cout << "WRONG";
//other code here
}
}
Method 2
Note that you can also use std::find_if instead of a for loop as shown below:
auto iter = std::find_if(mp.begin(), mp.end(), [](const std::pair<int,int>& elem)
{ return elem.second > 2;});
if (iter != mp.end())
std::cout << "Greater found ";
else
{
std::cout<<"Greater not found"<<std::endl;
}
Demo
your question is missing a lot of information and literarily , if you searched on web , you would find many ways to loop over unordered_map in C++ , but anyways , here is the edited version of your code with a test case:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
const int N = 10;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool x = true;
unordered_map<int, int> mp;
unordered_map<int, int>:: iterator it;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
mp[9] = 5;
for (it = mp.begin(); it != mp.end(); it++) {
cout << "key is " << it->first << " ,value is " << it->second << " " << endl;
if (it -> second > 2) {
cout << "WRONG";
x = false;
cout << "key is " << it->first << " ,value is " << it->second << " is greater than 2" << endl;
break;
}
}
return 0;
}
I would like to know how to display a message when a vector is empty. I know what is required but I don't know how to must be structured.
void displaypoints(const vector<int>& vec) {
cout << "[";
for (const auto& i : vec) {
cout << i << ' ';
}
cout << "]" << endl;
};
int main() {
vector <int> myvec {};
vector <int> newvec {1,2,3,4,5};
cout << "myvec";
displaypoints(myvec);
cout << "newvec";
displaypoints(newvec);
if (newvec.at(0) == 1) {
auto iq = find(newvec.begin(), newvec.end(), 1);
if (iq != newvec.end()) {
newvec.erase(iq);
}
if (newvec.begin(), newvec.end(), 2) {
auto ik = find(newvec.begin(), newvec.end(), 2);
if (ik!= newvec.end()) {
myvec.push_back(*ik);
newvec.erase(ik);
}
else if (newvec.begin(), newvec.end(), 3) {
auto ik = find(newvec.begin(), newvec.end(), 3);
if (ik!= newvec.end()) {
myvec.push_back(*ik);
newvec.erase(ik);
}
}
}
}
if (newvec.at(0) == 5) {
auto ik = find(newvec.begin(), newvec.end(), 5);
if (ik!= newvec.end()) {
myvec.push_back(*ik);
newvec.erase(ik);
}
}
displaypoints(newvec);
displaypoints(myvec);
}
The code above looks for the number 1, erases it then moves 2 to the myvec vector. If there is no 2 then it moves 3 because of the position 0 I have added. There is also another if statement that moves 5 if it is placed at position 0. What I want is another if statement to print a message if there is nothing in the newvec vector.
void displaypoints(vector<int> & vec){
if(vec.empty()){
cout<<"Vector Empty \n";
}
else {
//do your operations
}
}
whatever Ide you are using try first clean build and then build all and run the code it will work.
#include <algorithm>
#include <iostream>
#include <vector>
void
display_points(const std::vector<int>& v)
{
if (v.empty()) {
std::cout << "Empty vector.\n";
} else {
std::cout << "[ ";
for (const auto& i : v) {
std::cout << i << ' ';
}
std::cout << "]\n";
}
}
int
main()
{
std::vector<int> myvec;
std::vector<int> newvec{ 1, 2, 3, 4, 5 };
std::cout << "myvec: ";
display_points(myvec);
std::cout << "newvec:";
display_points(newvec);
int i = 1;
while (newvec.size() > 0) {
auto it = std::find(newvec.begin(), newvec.end(), i);
if (it != newvec.end()) {
myvec.push_back(*it);
newvec.erase(it);
}
++i;
}
std::cout << "myvec: ";
display_points(myvec);
std::cout << "newvec:";
display_points(newvec);
}
I ran into the following problem: suppose I have
pair<int, int> p(1,2)
vector<pair<int, int>> vec;
I want to use find to get the iterator pointing to the element p in the vector
find(vec.begin(), vec.end(), p)
But it gave me the error
type 'std::__1::pair<int, int>' does not provide a call operator
How should I proceed?
This is what I've used and it's worked great.
#include <iostream>
#include <vector>
#include <algorithm>
struct FindPair {
FindPair (int first, int second)
: m_first_value(first)
, m_second_value(second) { }
int m_first_value;
int m_second_value;
bool operator()
( const std::pair<int, int> &p ) {
return (p.first == m_first_value && p.second == m_second_value);
}
};
int main()
{
std::vector< std::pair<int, int> > myVec;
std::vector< std::pair<int, int> >::iterator it;
myVec.push_back(std::make_pair(1,1));
myVec.push_back(std::make_pair(1,2));
it = std::find_if(myVec.begin(), myVec.end(), FindPair(1, 2));
if (it != myVec.end())
{
// We Found it
std::cout << "Matched Found on Current Iterator!" << std::endl;
std::cout << "it.first: " << (*it).first << std::endl;
std::cout << "it.second: " << (*it).second << std::endl;
}
else
{
std::cout << "Nothing Matched!" << std::endl;
}
return 0;
}
Output:
Matched Found on Current Iterator!
it.first: 1
it.second: 2
I want to delete all elements which pair first == 0
Here code:
int main()
{
map<char, pair<int,string>> myMap;
map<char, pair<int,string>>::const_iterator it;
for (int i = 0; i < 10; i++)
{
char c = 'a' + i;
pair<int,string> p = make_pair(rand() % 2, "dd");
myMap.insert(make_pair(c,p));
}
it = find_if(myMap.begin, myMap.end(), isEqual);
}
bool isEqual(const pair<char, pair<int, string> > element)
{
return element.second.first == 0;
}
Error:
/usr/include/c++/4.8/bits/stl_algo.h:150: error: could not convert
'__first.std::_Rb_tree_iterator<_Tp>::operator*<std::pair<const char,
std::pair<int, std::basic_string<char> > > >()' from 'std::pair<const
char, std::pair<int, std::basic_string<char> > >' to 'std::pair<int,
std::basic_string<char> >'
while (__first != __last && !bool(__pred(*__first)))
Yes, of course.
I think I'd write the code something like this (I've added a bit of extra code to print out the contents of the map before and after the deletion to show that it worked):
#include <map>
#include <utility>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
ostream &operator<<(ostream &os, pair<int, string> const &p) {
return os << "[" << p.first << ", " << p.second << "]";
}
int main() {
map<char, pair<int, string>> myMap;
for (int i = 0; i < 10; i++) {
char c = 'a' + i;
pair<int, string> p = make_pair(rand() % 2, "dd");
myMap.insert(make_pair(c, p));
}
std::cout << "before:\n";
for (auto const &p : myMap)
std::cout << p.first << ": " << p.second << "\n";
map<char, pair<int, string> >::iterator it;
while (myMap.end() != (it = find_if(myMap.begin(), myMap.end(), [](auto p) { return p.second.first == 0; })))
myMap.erase(it);
std::cout << "\nafter\n\n";
for (auto const &p : myMap)
std::cout << p.first << ": " << p.second << "\n";
}
I would do this with a simple loop. You need to remember to keep track of the iterator when you erase an element from the map:
#include <map>
#include <ctime>
#include <string>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
int main()
{
std::srand(std::time(0));
std::map<char, std::pair<int, std::string>> myMap;
for(int i = 0; i < 10; i++)
{
char c = 'a' + i;
auto p = std::make_pair(rand() % 2, "dd");
myMap.insert(std::make_pair(c, p));
}
std::cout << "\nbefore:\n";
for(auto const& p: myMap)
{
std::cout << p.first;
std::cout << " {" << p.second.first;
std::cout << ", " << p.second.second;
std::cout << "}" << '\n';
}
// remove items in a simple loop
for(auto iter = myMap.begin(); iter != myMap.end();)
{
if(iter->second.first == 0)
iter = myMap.erase(iter); // grab new iterator when erasing
else
++iter; // otherwise just increment
}
std::cout << "\nafter:\n";
for(auto const& p: myMap)
{
std::cout << p.first;
std::cout << " {" << p.second.first;
std::cout << ", " << p.second.second;
std::cout << "}" << '\n';
}
}
Example Output:
before:
a {0, dd}
b {1, dd}
c {0, dd}
d {0, dd}
e {1, dd}
f {0, dd}
g {0, dd}
h {1, dd}
i {0, dd}
j {0, dd}
after:
b {1, dd}
e {1, dd}
h {1, dd}
I made a program that takes data from file, puts it into vector and then checks for most frequent element in the vector. (using map)
The problem is when I have same number of elements in the data (two Element1, two Element2, one Element3). It returns Element1 and I need it to pass the information that there is "no most frequent element".
My code looks like:
using namespace std;
bool comp(const pair<string, unsigned long> &pair1,
const pair<string, unsigned long> &pair2) {
return pair1.second < pair2.second;
}
string Odczyt::tokenizer() {
inFile.open("baza.txt");
while (!inFile.eof()) {
for (int i = 0; i < 4; i++) {
inFile >> row1[i] >> row2[i] >> row3[i] >> row4[i];
}
}
sVector1.assign(row1, row1 + 3);
string w1 = most_occurred(sVector1);
return w1;
}
string Odczyt::most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
for (vector<string>::const_iterator it = vec.begin(); it != vec.end();
++it) {
++str_map1[*it];
}
return max_element(str_map1.begin(), str_map1.end(), comp)->first;
}
Create a variable which stores the number of times you have found an element which occurs m times (where m is the current maximum number of times any element has occurred). If at the termination point of the algorithm you have more than one element appearing m times, then you know there is no single most-frequently-occurring element.
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
string most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
std::string max_element = "";
int max_count = 0;
typedef vector<string>::const_iterator iter;
iter end = vec.end();
for (iter it = vec.begin(); it != end; ++it) {
int count = ++str_map1[*it];
if(count == max_count) max_element = "no max found";
if(count > max_count) {
max_count = count;
max_element = *it;
}
}
return max_element;
}
int main() {
std::string arr1[5] = {"aa" , "bb", "cc", "dd", "ee"}; // no max found
std::string arr2[5] = {"aa" , "aa", "cc", "dd", "ee"};// aa
std::string arr3[5] = {"aa" , "aa", "cc", "cc", "ee"}; // no max found
std::vector<std::string> input1(arr1, arr1+5);
std::vector<std::string> input2(arr2, arr2+5);
std::vector<std::string> input3(arr3, arr3+5);
std::cout << most_occurred(input1) << std::endl;
std::cout << most_occurred(input2) << std::endl;
std::cout << most_occurred(input3) << std::endl;
}
the result is:
no max found
aa
no max found
The following test resulted in no max found.
int main() {
std::string arr1[24] = {"Element1", "Element2", "Element33", "1",
"Element1", "Element2", "Element33", "2", "Element11", "Element2",
"Element33", "2", "Element11" "Element21" "Element31", "2", "Element11",
"Element21", "Element31", "1", "Element12", "Element21", "Element31",
"1"}; // no max found
std::vector<std::string> input1(arr1, arr1+24);
std::cout << most_occurred(input1) << std::endl;
}
If the above code returns std::string("") then there was no max element, else it will return the max.
This is a frequent operation here is my sample code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <iterator>
using namespace std;
int main(int argc, char* argv[]) {
// number -> frequency
map<int, int> idfreq = {{1, 3}, {2, 10}, {3,8}, {9, 15}, {7,30}};
vector<pair<int, int> > v;
copy(idfreq.begin(), idfreq.end(), back_inserter(v));
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
make_heap(v.begin(), v.end(), [](const pair<int,int> &a, const pair<int,int> &b){ return a.second < b.second; });
// with -std=c++14
//make_heap(v.begin(), v.end(), [](auto& a, auto& b){ return a.second < b.second; });
cout << v.front().first << " " << v.front().second << " most frequent element\n";
cout << "after make heap call\n";
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
return 0;
}