passing a vector pair of integers into some function - c++

This is the problem statement:
Given an array of integers nums, sort the array in increasing order based on the frequency of the values. If multiple values have the same frequency, sort them in decreasing order.
Return the sorted array.
Below is the implementation of my code.
Can anyone help me figure out the way to pass these pair of integers into the second function?
class Solution {
public:
bool sortByVal(const pair<int,int>&a,const pair<int,int>&b)
{
if(a.second==b.second)
return a.first<b.first;
return a.second>b.second;
}
vector<int> frequencySort(vector<int>&a) {
int n=a.size();
vector<int>res;
unordered_map<int, int> m;
vector<pair<int, int> > v;
for (int i = 0; i < n; ++i) {
m[a[i]]++;
}
copy(m.begin(), m.end(), back_inserter(v));
sort(v.begin(), v.end(), sortByVal);
for (int i = 0; i < v.size(); ++i)
while(v[i].second--)
{
res.push_back(v[i].first);
}
return res;
}
};
Here is the link of the problem on leetcode:
https://leetcode.com/problems/sort-array-by-increasing-frequency/

Make sortByVal to be static member function.
If you want to stay with non-static version, you have to wrap this function into callable object passing this pointer - required to call a member function for object. Use bind, or bind_front (since c++20):
sort(v.begin(), v.end(), std::bind(&Solution::sortByVal,this,std::placeholders::_1,std::placeholders::_2));
sort(v.begin(), v.end(), std::bind_front(&Solution::sortByVal,this));
Demo

Related

How to sort std::set of indices according to the vector of sorted indices?

I have a class MyClass, which operates with some double values beta, stored as a class member, in it's member function g. It sorts them and stores the permutation in the class member std::vector<int> sorted_beta_ind:
double MyClass::g() {
// ...
sorted_beta_ind.resize(n);
for(unsigned int i=0; i<n; ++i) {
sorted_beta_ind[i] = i;
}
std::sort(sorted_beta_ind.begin(), sorted_beta_ind.end(),
[this] (const int &a, const int &b) {++op_cmp; return beta[a] > beta[b];});
// ...
}
Next I want to have several ordered sets of indices in another member function f, which will store the indices in the same order as in sorted_beta_ind. I'm trying to use std::set objects, and as such, I need a comparator. The best solution I figured out is a lambda function
double MyClass::f() {
auto ind_comp = [&order = sorted_beta_ind] (const int &a, const int &b) {
int pos_a = ~0, pos_b = ~0;
for(unsigned int i=0; i<order.size(); ++i) {
if(order[i] == a) {
pos_a = i;
}
if(order[i] == b) {
pos_b = i;
}
}
return pos_a < pos_b;
};
std::set<int, decltype(ind_comp)> d0, d1;
// the rest of the function which uses std::union and std::instersection
}
but on building the project I get
error: use of deleted function ‘MyClass::f()::<lambda(const int&, const int&)>& MyClass::f(int**, int)::<lambda(const int&, const int&)>::operator=(const MyClass::f()::<lambda(const int&, const int&)>&)’
Can this approach work or I should try something entirely else?
Capturing lambda expressions, like yours, are not DefaultConstructible. And that's exactly what std::set tries to do unless it receives a comparator object that can be copied from as a constructor call argument. That is:
std::set<int, decltype(ind_comp)> d0, d1;
Here std::set knows only the type of the comparator, and will attempt to constuct one using its default constructor. Instead, it should be:
std::set<int, decltype(ind_comp)> d0(ind_comp), d1(ind_comp);
// ~~~~~~~^ ~~~~~~~^

How to use a functor instead of lambda function

I was trying to solve a problem from Leetcode.
Problem description:
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
Note that it is the kth smallest element in the sorted order, not the kth distinct element.
I solved it like this:
class Solution {
public:
int kthSmallest(std::vector<std::vector<int>>& matrix, int k) {
auto comp_gt = [&matrix](std::pair<int ,int> a, std::pair<int ,int> b)
{
return matrix[a.first][a.second] > matrix[b.first][b.second];
};
m = matrix.size();
if (m == 0) return 0;
n = matrix[0].size();
if (n == 0) return 0;
std::priority_queue<std::pair<int, int>,
std::vector<std::pair<int, int>>,
decltype(comp_gt)> min_heap(comp_gt);
for (int j = 0; j < n; ++j)
{
min_heap.emplace(0, j);
}
for (int i = 0; i < k-1; ++i)
{
int r = min_heap.top().first;
int c = min_heap.top().second;
min_heap.pop();
if (r != m - 1)
{
min_heap.emplace(r+1, c);
}
}
return matrix[min_heap.top().first][min_heap.top().second];
}
private:
int m;
int n;
};
This code works. However, when I tried to replace the lambda function with a functor, I wrote the functor like this:
class comp_gt
{
bool operator () (std::pair<int, int> a, std::pair<int, int> b, std::vector<std::vector<int>>& matrix)
{
return matrix[a.first][a.second] > matrix[b.first][b.second];
}
};
then I realized I didn't know how to pass the matrix to a functor like [&matrix] in a lambda function.
Can anyone help?
You need to pass the reference in the constructor of the functor. Note that the below code is equivalent to your lambda, but with the mutable modifier.
class comp_gt
{
public:
using Matrix = std::vector<std::vector<int>>;
comp_gt(Matrix& matrix) : matrix{matrix}{}
bool operator () (std::pair<int, int> a, std::pair<int, int> b, std::vector<std::vector<int>>& matrix)
{
return matrix[a.first][a.second] > matrix[b.first][b.second];
}
private:
Matrix& matrix;
};
Then use it as:
comp_gt comp{matrix};
"How to use a functor instead of lambda function" - Create a class with operator() (that optionally captures variables). A lambda is nothing but syntactic sugar (an easier way) to write such a (functor) class.
This is done by passing it to the comparator's constructor:
class comp_gt
{
std::vector<std::vector<int>>& matrix;
comp_gt(std::vector<std::vector<int>>& matrix) : matrix{matrix} {}
Now, your existing operator() can use it normally.
Then, when you actually go about constructing the comparator, you just construct it normally and pass the appropriate parameter to the constructor. Let's say you wanted to use your comparator with std::sort:
comp_gt comparator{some_matrix};
std::sort(something.begin(), something.end(), comparator);
Using this comparator with std::priority_queue is analogous.

Proper way to initialize a vector of unique pointers in C++14

For initializing a vector of unique pointers in C++14, I can consider the following two ways. Which method is better?
#include<memory>
#include<vector>
using namespace std;
int main(){
const int N = 10000000;
{//first method
vector<unique_ptr<int>> vec(N);
for(auto it=vec.begin(); it!=vec.end();++it){
auto ptr = make_unique<int>();
*it = std::move(ptr);
}
}
{//second method
vector<unique_ptr<int>> vec;
for(int i=0; i<N; i++){
vec.push_back(make_unique<int>());
}
}
}
Either way works. The second is marginally more efficient if you reserve the correct capacity first. Personally, I think the standard algorithms are more expressive. I would do it like this:
std::vector<std::unique_ptr<int>> vec;
vec.reserve(N);
std::generate_n(std::back_inserter(vec), N, [] { return std::make_unique<int>(); });

merge sort with a comparator and a vector as arguments

The issue I'm having involves writing a function to use merge sort to sort a vector, and I need to use a functor as well. How can a comparator/functor be used as an argument to the merge sort function to sort a vector?
You could define a comparisor operator like this
struct MyLessThanFunctor
{
bool operator() (int i,int j)
{
return (i<j);
}
};
And after that, instancing it and using it
MyLessThanFunctor comparator;
sort(elements, comparator);
!!!Warning std::sort is not expected to be a stable sorting algorithm.
Use std::stable_sort which is most of the times implemented as merge sort.
struct comparator
{
bool operator () (int i1, int i2) const { return i1 < i2; }
};
int main()
{
vector<int> v = {0,13,76,46,53,22,4,68,68,94,38,52,83,3,5,53,67 };
std::stable_sort (v.begin(), v.end(), comparator() );
for (auto e : v) cout << e << " " ;
}

How to return a 2 dimensional vector?

I have a function that creates a 2D vector
void generate(int n)
{
vector< vector<int> > V (n, vector<int>(1 << n , 0 ));
.......
}//n is used to determine the size of vector
Now, I need to return the created vector to use it in another function .If I did
return V ;
it will be wrong because V is a local variable but I can't define V outside the function because this functions defines the size of V . What should I do ?
You can return V with no issues - it will return a copy of the local variable. Issues only arise when you return a reference or pointer to a variable with local scope; when the function ends, the local variable falls out of scope and is destroyed and the reference/pointer is no longer valid.
Alternatively, you can accept a reference to a vector as your argument, write to it and return void:
void generate(int n, std::vector< std::vector<int> >& vec) {
vec.resize(n, std::vector<int>(1 << n, 0));
}
int main() {
std::vector< std::vector<int> > v;
generate(10, v);
}
This is faster than returning a copy of the local member, which can be expensive for large objects such as multi-dimensional vectors.
vector<vector<int> > generate(int n)
{
vector<vector<int> > v(n, vector<int>(1 << n, 0));
//...
return v;
}
The return value is a copy of the local variable v so there is no problem at all.
If you're concerned about copying the vector, maybe you could do something like this:
void generate(int n, vector<vector<int> >& v)
{
v.clear(); //not necessary if you're sure it's empty
v.resize(n, vector<int>(1 << n, 0));
//...
}
if the vector is small, just return it by value, it will be copied.
if the vector is large, the caller can pass the dest vector by reference.
As alternative to other answers you can return pointer to heap allocated vector. For securing from memory leaks you can use "move constructor" idiom.
typedef auto_ptr<vector<vector<int> > > vector_ptr;
vector_ptr generate(int n)
{
vector_ptr V(new vector<vector<int> >(n, vector<int>(1 << n , 0 )));
return V;
}
// ...
vector_ptr V(generate(some_number));
This idiom can be used for any "heavy" object. If you whant to prolonge lifetime of returned object you can assign it to shared_ptr (as example boost::shared_ptr). But I think it is better return copy whenever it is possible, for minimizing complexity of your code.
Just like we do for other,we can do that here also.See my code for better explanation I have given my code for matrix multiplication in which i have made a function for it and returned a matrix as a 2D vector.
`
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> mul(vector<vector<int>> a,vector<vector<int>> b)
{
int n=a.size();
int k=a[0].size();
int m=b[0].size();
vector<vector<int>> c(n,vector<int> (m,0));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
c[i][j]=0;
for(int m=0;m<k;m++)
{
c[i][j]+=(a[i][m]*b[m][j]);
}
}
}
return c;
}
int main() {
vector<vector<int>> l={{1,2}};
vector<vector<int>> r={{1,2,3},{4,5,6}};
vector<vector<int>> m;
m=mul(l,r);
for(int i=0;i<m.size();i++)
{
for(int j=0;j<m[i].size();j++)
{
cout<<m[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
`