I'm new to C++. I was trying a leetcode question (436. Find Right Interval). Thought of complicating it by writing my own lower_bound just for my knowledge. But the below code is showing me runtime error: reference binding to null pointer of type 'value_type' (stl_vector.h). I'm unable to understand what's the issue, would someone please clarify what I'm doing wrong.
class Solution {
public:
vector<int> findRightInterval(vector<Interval>& intervals) {
int n = intervals.size();
vector<int> res;
vector<pair<Interval, int>> s_i;
for(int i = 0; i<n; i++) {
s_i.push_back(make_pair(intervals[i], i));
}
sort(s_i.begin(), s_i.end(), [](const pair<Interval, int>& a, const pair<Interval, int> &b) -> bool {
return a.first.start < b.first.start;
});
for(auto x : s_i) {
cout<<"["<<x.first.start<<","<<x.first.end<<"],"<<x.second<<endl;
}
for(int i = 0; i<n; i++) {
int val = intervals[i].end;
cout<<val<<endl;
//pair<Interval, int> temp = make_pair(Interval(val, val), 0);
auto it = lower_bound(s_i.begin(), s_i.end(), val,
[](const pair<Interval, int> &a, int val) -> bool {
return a.first.start < val;
});
if (it != s_i.end()) {
res[i] = it->second;
} else {
res[i] = -1;
}
}
return res;
}
};
Related
The thing is that I am implementing a recursion, in which I have to use NULL value to specify that the recursion branch being traversed is invalid.
But in C++ we can't return NULL when the return type is a container( vector container in my case).
So is there any workaround for the problem or do I have to use some other logic?
Code:
#include<iostream>
#include<vector>
std::vector<int> howSum(int target,std::vector<int> in){
if(target < 0 ) return {-1};
if(target == 0) return {};
for(int num : in){
int remainder = target - num ;
std::vector<int> remResult = howSum(remainder,in);
if(remResult[0] != -1 || remResult.empty()){
remResult.push_back(num);
return remResult;
}
}
return {-1};
}
int main(){
std::vector<int> v = {2,4,3};
int targetSum = 8;
std::vector<int> r = howSum(targetSum,v);
for(int o : r)
std::cout<<o<<" ";
return 0;
}
Edit:
I'm very thankful for all the suggestions and solution but thing I wanted was a primitive solution that didn't use more recent c++ compilations(i.e c++17 and c++20).
Also If possible please check out my primitive solution which I implemented and suggest something if this can be improved.
An alternate solution I found out myself (primitive solution)
I am writing this for people visiting this question for reference.
Solution:
#include<iostream>
#include<vector>
#include<string>
std::string howSum(int target,std::vector<int> v){
if(target == 0) return "";
if(target < 0) return "null";
for(int num : v){
int rem = target - num;
std::string remRes = howSum(rem,v);
if(remRes != "null"){
remRes += std::to_string(num);
remRes += " ";
return remRes;
}
}
return "null";
}
int main()
{
std::vector<int> v = {2,3,4};
int targetSum = 8;
std::cout<<howSum(targetSum,v);
return 0;
}
My Dynamic Problem Solution
#include<iostream>
#include<vector>
#include<string>
#include<unordered_map>
std::unordered_map<int,std::string> mem;
std::string howSum(int target, std::vector<int> v){
if(mem.find(target) != mem.end())
return mem[target];
if(target == 0) return "";
if(target < 0) return "null";
for(int num : v){
int rem = target - num;
std::string remRes = howSum(rem,v);
if(remRes != "null"){
remRes += std::to_string(num);
remRes += " ";
mem[target] = remRes;
return mem[target];
}
}
mem[target] = "null";
return mem[target];
}
int main()
{
std::vector<int> v = {7,14};
int targetSum = 300;
std::cout<<howSum(targetSum,v);
return 0;
}
You have the following options:
Return result + bool
Return std::pair<std::vector<int>, bool>, or even better a struct like this
struct Result {
std::vector<int> result;
bool is_valid;
};
Result howSum(int target, const std::vector<int>& in);
where bool would indicate whether or not the result vector is actually usable.
Output parameter
Return a bool indicating whether the operation was successful and use an output parameter (note that a non-const reference is used for the output parameter so that it can be modifier from within the function and later used outside of it):
bool howSum(int target, const std::vector<int>& in, std::vector<int>& result);
optional
Either use std::optional with C++17 or a similar boost::optional from boost library:
std::optional<std::vector<int>> howSum(int target, const std::vector<int>& in);
Casting std::optional to bool or using has_value method checks whether you have an actual result returned.
Note that in each of the cases it's better to pass the input vector by const & to avoid unnecessary copies.
with optional (c++17), you could do something like this
#include<iostream>
#include<vector>
#include<optional>
std::optional<std::vector<int>> howSum(int target,std::vector<int> in){
if(target <= 0 ) return {}; // returns "empty" optional
auto num = in.back();
in.pop_back();
int remainder = target - num ;
auto maybe_r = howSum(remainder, in);
if (!maybe_r.has_value())
return howSum(target, in);
else {
auto r = maybe_r.value();
r.push_back(num);
return r;
}
}
int main(){
std::vector<int> v = {2,4,3,1};
int targetSum = 8;
auto maybe_r = howSum(targetSum,v);
if (!maybe_r.has_value()) {
std::cout << "no result\n";
} else {
auto r = maybe_r.value();
for(int o : r)
std::cout<<o<<" ";
}
return 0;
}
I am trying to write sorting template function to make it work with custom classes.
My code is:
#include <iostream>
#include <vector>
struct test
{
int value;
test(int a) : value(a){};
void print() { printf("the value is : %d", value); };
};
template <class T>
void bubblesort(T *m_data, size_t size, bool (*cmp)(const T &l, const T &r))
{
for (uint32_t i = 0; i < size; i++)
for (uint32_t j = 1; j < size - i; j++)
if (cmp(m_data[j - 1], m_data[j]))
{
T temp = m_data[j];
m_data[j] = m_data[j - 1];
m_data[j - 1] = temp;
}
}
int main()
{
std::vector<test> arr;
for (size_t i = 0; i < 10; i++)
arr.emplace_back(i);
std::vector<test *> arr1;
for (auto &i : arr)
arr1.emplace_back(&i);
bubblesort<test>(&arr[0], arr.size(), [](const test &l, const test &r) { return l.value < r.value; });
// bubblesort<test*>(&arr1[0], arr1.size(), [](const test *&l, const test *&r) { return l->value < r->value; });
for (auto i : arr)
printf("%d\n", i.value);
}
My question is how do you sort arr1 using the bubblesort function above? What kind of modification do I have to make in my code to be able to do so?
uncommenting the bubblesort line gives error
error: invalid user-defined conversion from 'main()::<lambda(const test*&, const test*&)>' to 'bool (*)(test* const&, test* const&)' [-fpermissive]
[build] 48 | bubblesort<test *>(&arr1[0], arr1.size(), [](const test *&l, const test *&r) { return l->value < r->value; });
Your function has the wrong type; T is test*, so you need test* const& - "reference to const pointer to test" - as the error message says.
(const test*& is "reference to pointer to const test.)
Your solution cannot work with templates...it cannot deduce the parameters type.
Consider modifying your code as follow:
struct test
{
int value;
explicit test(int a) : value(a) {};
void print() { printf("the value is : %d", value); };
};
template <class T, class _cmp>
void bubblesort(T *m_data, size_t size, _cmp cmp)
{
for (uint32_t i = 0; i < size; i++)
for (uint32_t j = 1; j < size - i; j++)
if (cmp(m_data[j - 1], m_data[j]))
{
T temp = m_data[j];
m_data[j] = m_data[j - 1];
m_data[j - 1] = temp;
}
}
int main()
{
std::vector<test> arr;
for (int i = 0; i < 10; i++)
arr.emplace_back(i);
std::vector<test *> arr1;
for (auto i : arr)
arr1.emplace_back(&i);
bubblesort<test>(&arr[0], arr.size(), [](const test &l, const test &r) -> bool { return l.value < r.value; });
bubblesort<test*>(&arr1[0], arr1.size(), [](const test* l, const test* r) -> bool { return l->value < r->value; });
for (auto i : arr)
printf("%d\n", i.value);
}
I want to use structure Item as key in unordered_map
I implemented structures for hash and equal operations.
But I have an error
hashtable_policy.h:1384:16: error: no match for call to '(const ItemHash) (const Item&)'
solution.cpp:28:12: note: candidate: 'size_t ItemHash::operator()(Item)'
32 | size_t operator()(Item item) {
solution.cpp:28:12: note: passing 'const ItemHash*' as 'this' argument discards qualifiers
How can I fix the error?
My code
vector<int> get_key(const string& s) {
vector<int> res(26, 0);
for (int i = 0; i < s.size(); ++i) {
int pos = s[i] - 'a';
res[pos]++;
}
return res;
}
struct Item {
vector<int> v;
Item(const vector<int>& vec) : v(vec) {}
bool operator==(Item other) {
if (v.size() != other.v.size()) {
return false;
}
for (int i = 0; i < v.size(); ++i) {
if (v[i] != other.v[i]) {
return false;
}
}
return true;
}
};
struct ItemHash {
size_t operator()(Item item) {
auto vec = item.v;
size_t seed = vec.size();
for(auto& i : vec) {
seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
struct ItemEqual {
bool operator()(Item item1, Item item2) {
return item1 == item2;
}
};
vector<vector<int> > Solution::anagrams(const vector<string> &A) {
vector<vector<int>> res;
unordered_map<Item, vector<int>, ItemHash, ItemEqual> hash; // hash_key, vector of indexes
for (int i = 0; i < A.size(); ++i) {
Item item = Item(get_key(A[i]));
hash[item].push_back(i);
}
for (const auto& i : hash) {
res.push_back(i.second);
}
return res;
}
You need to const-qualify ItemHash::operator()(Item), i.e.,
struct ItemHash {
size_t operator()(Item item) const
// ^^^^ here
{
// as before...
}
Note that as #JeJo pointed out in the comments, you need the same fix for ItemEqual.
I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}
I'm attempting to create an algorithm in C++ which will give me all of the possible combinations of a set of list items (input in a map format). I want to avoid duplicates and make sure to cover all possible combinations. To simplify the example, here's what the input may look like:
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
I'd feed this map into the algorithm, and it should spit out a vector with all of the possible combinations (using one of each key type):
wheat+ham+lettuce+mustard
wheat+turkey+lettuce+mustard
wheat+roastbeef+lettuce+mustard
white+ham+lettuce+mustard
white+turkey+lettuce+mustard
white+roastbeef+lettuce+mustard
It needs to work for any map of string vectors. So far I've tried and gotten close, but I end up with duplicate combinations and missed combinations:
sandwichList getCombinations(sandwichMap sMap)
{
locList retList;
int totalCombos = 1;
for (sandwichMapIt i = sMap.begin(); i != sMap.end(); ++i)
{
totalCombos *= i->second.size();
}
retList.resize(totalCombos);
int locCount;
for (sandwichMapIt a = sMap.begin(); a != sMap.end(); ++a)
{
locCount = 0;
for (locListIt l = a->second.begin(); l != a->second.end(); ++l)
{
for (unsigned int i = 0; i < totalCombos / a->second.size(); ++i)
{
retList[i + a->second.size() * locCount] += *l;
}
locCount++;
}
}
return retList;
}
Any help would be greatly appreciated!
Updated code:
#include <vector>
#include <map>
#include <list>
#include <iostream>
typedef std::vector<std::string> strVec;
typedef std::list<std::string> strList;
typedef std::map<std::string, strVec> sandwichMap;
int main()
{
sandwichMap sMap;
sMap["bread"].push_back("wheat");
sMap["bread"].push_back("white");
sMap["meat"].push_back("ham");
sMap["meat"].push_back("turkey");
sMap["meat"].push_back("roastbeef");
sMap["veggie"].push_back("lettuce");
sMap["sauce"].push_back("mustard");
strList finalSandwichList;
for (sandwichMap::iterator i = sMap.begin(); i != sMap.end(); ++i)
{
strList tmpSandwich;
for (strVec::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
if (finalSandwichList.empty())
{
tmpSandwich.push_back(*j);
}
else
{
for (strList::iterator k = finalSandwichList.begin(); k != finalSandwichList.end(); ++k)
tmpSandwich.push_back(*k + "+" + *j);
}
}
tmpSandwich.swap(finalSandwichList);
}
for (strList::iterator i = finalSandwichList.begin(); i != finalSandwichList.end(); ++i)
{
std::cout << *i << std::endl;
}
return 0;
}
//solution
std::list<std::string> result;
for(auto i=sandwichMap.begin(); i!=sandwichMap.end(); ++i) {
std::list<std::string> new_result;
for(auto j=i->second.begin(); j!=i->second.end(); ++j) {
if(result.empty())
new_result.push_back(*j);
else
for(auto k=result.begin(); k!=result.end(); ++k)
new_result.push_back(*k + "+" + *j);
}
new_result.swap(result);
}
This should work :
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
map<string, vector<string>> sMap;
vector<string> add;
int sett[200], countt;
void solve(map<string, vector<string>>::iterator itt, int ct, vector<string> addd){
vector<string> tmp = itt->second;
if(ct == countt){
for(int j=0;j<addd.size();j++){
cout<<addd[j]<<" ";
}
cout<<endl;
return;
}
itt++;
for(int i=0;i<tmp.size();i++){
//cout<<tmp[i]<<" ";
addd.push_back(tmp[i]);
solve(itt, ct+1, addd);
vector<string>::iterator tempIt = addd.end();
addd.erase(tempIt--);
}
}
int main(){
sMap["bre"].push_back("wh");
sMap["bre"].push_back("whi");
sMap["me"].push_back("ham");
sMap["me"].push_back("tur");
sMap["me"].push_back("rr");
sMap["veg"].push_back("let");
sMap["sau"].push_back("mus");
countt = sMap.size();
solve(sMap.begin(), 0, add);
return 0;
}
I have used backtracking to evaluate every possible combination.
Note : it is in c++11 you might need to change some part of the code for lower version of c++
link to output : http://ideone.com/Ou2411
The code is kinda long because of the helper methods, but it does the job:
#include <vector>
#include <string>
#include <map>
#include <iostream>
using namespace std;
template <class T>
vector<T> Head(const vector<T> &v) {
return vector<T>(v.begin(), v.begin() + 1);
}
template <class T>
vector<T> Tail(const vector<T> &v) {
auto first = v.begin() + 1;
auto last = v.end();
return vector<T>(first, last);
}
template <class T>
vector<T> Concat(const vector<T> &v1, const vector<T> &v2) {
vector<T> result = v1;
result.insert(result.end(), v2.begin(), v2.end());
return result;
}
vector<vector<string>> CombineVectorWithScalar(const vector<vector<string>> &v, const string &scalar) {
vector<vector<string>> result = v;
for (unsigned i = 0; i < v.size(); i++) {
result[i].push_back(scalar);
}
return result;
}
vector<vector<string>> CombineVectorWithVector(const vector<vector<string>> &v1, const vector<string> &v2) {
if (v2.empty()) {
return vector<vector<string>>();
}
else {
auto headCombination = CombineVectorWithScalar(v1, v2.front());
auto tailCombination = CombineVectorWithVector(v1, Tail(v2));
return Concat(headCombination, tailCombination);
}
}
vector<string> GetKeys(const map<string, vector<string>> &mp) {
vector<string> keys;
for (auto it = mp.begin(); it != mp.end(); ++it) {
keys.push_back(it->first);
}
return keys;
}
vector<vector<string>> CombineMapValues(const map<string, vector<string>> &mp) {
vector<string> keys = GetKeys(mp);
vector<vector<string>> result;
auto &firstVector = mp.begin()->second;
for (auto it = firstVector.begin(); it != firstVector.end(); ++it) {
vector<string> oneElementList;
oneElementList.push_back(*it);
result.push_back(oneElementList);
}
vector<string> restOfTheKeys = Tail(keys);
for (auto it = restOfTheKeys.begin(); it != restOfTheKeys.end(); ++it) {
auto ¤tVector = mp.find(*it)->second;
result = CombineVectorWithVector(result, currentVector);
}
return result;
}
void PrintCombinations(const vector<vector<string>> & allCombinations) {
for (auto it = allCombinations.begin(); it != allCombinations.end(); ++it) {
auto currentCombination = *it;
for (auto itInner = currentCombination.begin(); itInner != currentCombination.end(); ++itInner) {
cout << *itInner << " ";
}
cout << endl;
}
}
int main() {
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
auto allCombinations = CombineMapValues(sandwichMap);
PrintCombinations(allCombinations);
return 0;
}
void generate_all(std::map<std::string,std::vector<std::string>>::iterator start,
std::vector<std::string::iterator> accomulator,
std::map<std::string,std::vector<std::string>>& sMap){
for (auto it=start; it!=sMap.end(); ++it){
for (auto jt=it->second.begin(); jt!=it->second.end(); jt++){
generate_all(start+1,accomulator.pus_back[jt],sMap);
}
}
if (accomulator.size() == sMap.size()){
// print accomulator
}
}
Call with generate_all(sMap.begin(),aVector,sMap);
If the map is too big to go recursively, you can always generate an equivalent iterative code.
This solution is not recursive. Basically what it does is the following:
Compute how many combinations are actually possible
Know that for each key in the map, you're going to have to add nrCombinations/nrItemsInKey of them in total.
You can see it as a tree growing, branching more and more the more keys you have visited.
If you keep track of how many there are, how spaced they are and where they start you can automatically fill all combinations.
Code
#include <vector>
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, std::vector<std::string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
sandwichMap["sauce"].push_back("mayo");
// Compute just how many combinations there are
int combinationNr = 1;
for ( auto it : sandwichMap ) {
combinationNr *= it.second.size();
}
std::vector<std::vector<std::string>> solutions(combinationNr);
// We start with empty lists, thus we only have one cluster
int clusters = 1, clusterSize = combinationNr;
for ( auto category : sandwichMap ) {
int startIndex = 0;
int itemsNr = category.second.size();
int itemsPerCluster = clusterSize / itemsNr;
for ( auto item : category.second ) {
for ( int c = 0; c < clusters; ++c ) {
for ( int i = 0; i < itemsPerCluster; ++i ) {
// We sequentially fill each cluster with this item.
// Each fill starts offset by the quantity of items
// already added in the cluster.
solutions[startIndex+i+c*clusterSize].push_back(item);
}
}
startIndex += itemsPerCluster;
}
clusters *= itemsNr;
clusterSize = combinationNr / clusters;
}
for ( auto list : solutions ) {
for ( auto element : list ) {
std::cout << element << ", ";
}
std::cout << "\n";
}
return 0;
}