Runtime error for Leetcode question: Two Sum - c++

Error:
Line 1034: Char 9: runtime error: reference binding to null pointer of type 'int' (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:9
My Code:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> sol;
int temp, i = 0, l = nums.size();
while(true && i < l)
{
temp = nums[i] - target;
int it = nums.end() - find(nums.begin(), nums.end(), temp);
if(it == 0)
{ i++;
continue;
}
sol[0] = i;
sol[1] = it;
break;
}
return sol;
}

The problem statement from Two Sum - LeetCode says:
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
The bigger issue in the posted implementation is the repeated access out of bounds of sol, which is declared as an empty vector:
vector<int> sol;
Later, in loop, it's accessed via operator[] at indices 0 and 1, but those elements don't exist. So, to fix it, just declare a vector of two elements.
std::vector<int> sol(2);
Other minor issues (not really errors) are the followings:
int temp, i = 0, l = nums.size();
while ( true && i < l )
{ // ^^^^^^^ Why? It's pointless.
int it = nums.end() - find(nums.begin(), nums.end(), temp);
// ^^^^^^^^^^^^
// This traverses the vector every time from the beginning, which is a waste.
// Also, "you may not use the same element twice".
// Just start from the element after nums[i].
if(it == 0) // Consider to invert the logic: break when a pair is found
{
i++;
continue;
}
sol[0] = i; // Already addressed, but...
sol[1] = it;
// ^^ I lied, this IS another error.
// Do you remember how 'it' was calculated?
break;
}
To summarize, this is a possible solution
std::vector<int> twoSum(std::vector<int> const& nums, int target)
{ // We are not modifying it, so ^^^^^
std::vector<int> sol(2);
// IMHO, a std::pair would have been a better fir, here.
for (auto i{ nums.cbegin() }; i != nums.cend(); ++i)
{ // It's const... ^
auto const j = std::find(i + 1, nums.cend(), *i - target);
// Don't count twice ^^^^^
if( j != nums.cend() )
{ // ^^
sol[0] = std::distance(nums.cbegin(), i);
sol[1] = std::distance(nums.cbegin(), j);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Count from the beginning.
break;
}
}
return sol;
}

Related

Problems with vectors, how to remove the arrays in my vectors?

I have created a function that creates all the possible solutions for a game that I am creating... Maybe some of you know the bullcow game.
First I created a function that creates a combination of numbers of max four integers and the combination can't have any repeating number in it... like...
'1234' is a solution but not '1223' because the '2' is repeating in the number. In total there is 5040 numbers between '0123' and '9999' that haven't repeating numbers.
Here is my function:
std::vector <std::array<unsigned, 4>> HittaAllaLosningar(){
std::vector <std::array<unsigned, 4>> Losningar;
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
for (unsigned k = 0; k < 10; k++) {
for (unsigned l = 0; l < 10; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
Losningar.push_back({i,j,k,l});
}
}
}
}
}
return Losningar;
}
Now let's say I have the number '1234' and that is not the solution I am trying to find, I want to remove the solution '1234' from the array since that isn't a solution... how do I do that? have been trying to find for hours and can't find it. I have tried vector.erase but I get errors about unsigned and stuff... also its worth to mention the guesses are in strings.
What I am trying to do is, to take a string that I get from my program and if it isn't a solution I want to remove it from the vector if it exists in the vector.
Here is the code that creates the guess:
std::string Gissning(){
int random = RandomGen();
int a = 0;
int b = 0;
int c = 0;
int d = 0;
for (unsigned i = random-1; i < random; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j == 0) {
a = v[i][j];
}
if (j == 1) {
b = v[i][j];
}
if (j == 2) {
c = v[i][j];
}
if (j == 3) {
d = v[i][j];
}
}
std::cout << std::endl;
AntalTry++;
}
std::ostringstream test;
test << a << b << c << d;
funka = test.str();
return funka;
}
The randomgen function is just a function so I can get a random number and then I go in the loop so I can take the element of the vector and then I get the integers of the array.
Thank you very much for taking your time to help me, I am very grateful!
You need to find the position of the element to erase.
std::array<unsigned, 4> needle{1, 2, 3, 4};
auto it = std::find(Losningar.begin(), Losningar.end(), needle);
if (it != Losningar.end()) { Losningar.erase(it); }
If you want to remove all the values that match, or you don't like checking against end, you can use std::remove and the two iterator overload of erase. This is known as the "erase-remove" idiom.
std::array<unsigned, 4> needle{1, 2, 3, 4};
Losningar.erase(std::remove(Losningar.begin(), Losningar.end(), needle), Losningar.end());
To erase from a vector you just need to use erase and give it an iterator, like so:
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
auto it = vec.begin(); //Get an iterator to first elements
it++; //Increment iterator, it now points at second element
it = vec.erase(it); // This erases the {4,3,2,1} array
After you erase the element, it is invalid because the element it was pointing to has been deleted. Ti continue to use the iterator you can take the return value from the erase function, a valid iterator to the next element after the one erased, in this the case end iterator.
It is however not very efficient to remove elements in the middle of a vector, due to how it works internally. If it's not important in what order the different solution are stored, a small trick can simplify and make your code faster. Let's say we have this.
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
vec.push_back({3,2,1,4});
To remove the middle one we then do
vec[1] = vec.back(); // Replace the value we want to delete
// with the value in the last element of the vector.
vec.pop_back(); //Remove the last element
This is quite simple if you have ready other functions:
using TestNumber = std::array<unsigned, 4>;
struct TestResult {
int bulls;
int cows;
}
// function which is used to calculate bulls and cows for given secred and guess
TestResult TestSecretGuess(const TestNumber& secret,
const TestNumber& guess)
{
// do it your self
… … …
return result;
}
void RemoveNotMatchingSolutions(const TestNumber& guess, TestResult result)
{
auto iter =
std::remove_if(possibleSolutions.begin(),
possibleSolutions.end(),
[&guess, result](const TestNumber& possibility)
{
return result == TestSecretGuess(possibility, guess);
});
possibleSolutions.erase(iter, possibleSolutions.end());
}
Disclaimer: it is possible to improve performance (you do not care about order of elements).

Increasing Sequence C++

I try to solve this challenge on CodeFights, but, it doesn't work. My best solution got 25/26 (time limit exceeded on the last test) but I deleted that because I tried it yesterday (it was O(n^2)). Now I tried a new one in O(n). I am very tired and I really want to get this done today, so please help me.
Here are the statements:
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Example
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
And here is my code until now... (poor code):
#include <iostream>
#include <vector>
#include <algorithm>
bool almostIncreasingSequence(std::vector<int> sequence)
{
int count = 0;
for(int i = 0; i < sequence.size()-1; i++)
{
if(sequence[i] > sequence[i+1])
{
count++;
sequence.erase(sequence.begin(), sequence.begin() + i);
i--;
}
if(count == 2)
return false;
}
return true;
}
int main()
{
std::cout << std::endl;
return 0;
}
Here is a C++11 solution with O(N) runtime:
constexpr auto Max = std::numeric_limits<std::size_t>::max();
bool is_sorted_but_skip(const std::vector<int>& vec, std::size_t index = Max){
auto Start = index == 0 ? 1 : 0;
auto prev = vec[Start];
for(std::size_t i = Start + 1; i < vec.size(); i++){
if(i == index) continue;
if(prev >= vec[i]) return false;
prev = vec[i];
}
return true;
}
bool almostIncreasingSequence(std::vector<int> v)
{
auto iter = std::adjacent_find(v.begin(), v.end(), [](int L, int R){ return L >= R; });
if(is_sorted_but_skip(v, std::distance(v.begin(), iter)))
return true;
return is_sorted_but_skip(v, std::distance(v.begin(), std::next(iter)));
}
We use std::adjacent_find to find the first element, iter greater than or equal its next element. Then we check that sequence is strictly sorted while skipping iter's position.
Otherwise, we check that the sequence is strictly sorted while we skip iter+1's position
Worse case complexity: 3 linear scan
Demo
Here's a hint (well, almost a solution really):
If you see a decrease between one element to the next, then you have to remove one of them (*).
Now, what if you find two decreases, between two disjoint pairs of elements? That's right :-)
Keeping that in mind, you should be able to solve your problem using a linear scan and a bit of constant-time work.
(*) excluding the first and the last pair of elements.
This is still O(N^2), because you delete the first element of the vector in each iteration. Don't delete the first element and don't i-- in the loop.
If you must erase the numbers (you don't, but still), at least do it from the end of the list. That way erasing a number is probably an O(1) operation (I'm not 100% sure that's how std::vector is implemented).
You really don't have to erase the numbers.
#include<iostream>
#include<vector>
using namespace std;
int almostIncreasingSequence( vector<int> sequence );
int main(){
int array[] = {40, 50, 60, 10, 20, 30};
std::vector<int> vect (array, array + sizeof(array) / sizeof(int) );
bool ret = almostIncreasingSequence(vect);
if( ret ){
std::cout<<"Array is strictly increasing.";
}
else{
std::cout<<"Array is not strictly increasing.";
}
return 0;
}
bool almostIncreasingSequence(std::vector<int> sequence) {
int val = 0;
int currentBig = sequence.at(0);
for (int i = 1; i < sequence.size(); i++){
if( currentBig < sequence.at(i))
{
currentBig = sequence.at(i);
}
else{
val++;
if( val>1)
{
return false;
}
if( i > 1 ){
if (sequence.at(i) > sequence.at(i-2)){
if( currentBig < sequence.at(i) ){
}
else{
currentBig = sequence.at(i);
}
}
}
else{
currentBig = sequence.at(i);
}
}
}
return true;
}

Which index does iterator pointing to

There is an iterator to a vector. I want to know which index does iterator pointing to. So I made following but I am not sure.
int temp = -1;
std::vector <int> ::iterator f;
for (f=eFace[e].begin(); f!=eFace[e].end(); ++f)
{
if (*f == face)
{
switch (f-eFace[e].begin())
{
case 0:
temp = 5;
break;
case 1:
temp = 3;
break;
case 2:
temp = 4;
break;
case 3:
temp = 1;
break;
case 4:
temp = 2;
break;
case 5:
temp = 0;
break;
default:
throw;
}
break;
}
}
std::vector<int>::size_type index = std::distance (eFace [e].begin(), f);
Note that this can be slow if you execute it every loop though. Another option for vectors would be:
std::vector<int>::size_type index = f - eFace [e].begin();
This works because vectors use a random-access iterator, which is required to have subtraction defined, as pointed out by Steve Jessop below.
Why not something like this :
std::vector <int> ::iterator f;
int index = 0;
for (f=eFace[e].begin(); f!=eFace[e].end(); ++f)
{
// do sth
index++;
}
Getting clearer code would be much easier.
First, finding a value in a vector:
// Returns the index of `face` in `vec`.
// If `face` is not present in `vec`, returns `vec.size()`.
size_t findFaceIndex(int const face, std::vector<int> const& vec) {
std::vector<int>::const_iterator const it =
std::find(vec.begin(), vec.end(), face);
return it - vec.begin();
}
And now mapping:
static int const FaceMap[] = { 5, 3, 4, 1, 2, 0 };
static size_t const FaceMapSize = sizeof(FaceMap)/sizeof(int);
// Translate face index into ...
int faceIndexToX(size_t const index) {
if (index >= FaceMapSize) { throw std::runtime_error("out of bounds"); }
return FaceMap[index];
}
For your question "I want to know which index does iterator pointing to." by saying std::vector<int>::iterator f = eFace.begin(); you are creating an interator that would be similar to the index approach by saying std::vector<int>::size_type i = 0;.
With iterators you use eFace.begin() and != eFace.end() the same way you would use i = 0 and != eFace.size() when walking through a vector with a for loop.
At least I think that's what your original question was.
I wonder why you need the index of an array when you have the iterator anyway? Provided the iterator is random access you can subtract it from begin(), but if the index is so important I wonder if you're better off just using that rather than an iterator - of course it depends on whether you have access to the code to refactor it.
I'm not sure quite what you're trying to achieve with your switch but if it's to map values then presumably a sparse vector would be far more appropriate?

Problem with Mergesort in C++

vector<int>& mergesort(vector<int> &a) {
if (a.size() == 1) return a;
int middle = a.size() / 2;
vector<int>::const_iterator first = a.begin();
vector<int>::const_iterator mid = a.begin() + (middle - 1);
vector<int>::const_iterator last = a.end();
vector<int> ll(first, mid);
vector<int> rr(mid, last);
vector<int> l = mergesort(ll);
vector<int> r = mergesort(rr);
vector<int> result;
result.reserve(a.size());
int dp = 0, lp = 0, rp = 0;
while (dp < a.size()) {
if (lp == l.size()) {
result[dp] = (r[rp]);
rp++;
} else if (rp == r.size()) {
result[dp] = (l[lp]);
lp++;
} else if (l[lp] < r[rp]) {
result[dp] = (l[lp]);
lp++;
} else {
result[dp] = (r[rp]);
rp++;
}
dp++;
}
a = result;
return a;
}
It compiles correctly but while execution, I am getting:
This application has requested the
runtime to end it in an unusual way.
This is a weird error.
Is there something that is fundamentally wrong with the code?
This result.reserve(a.size()) just affects the vector's capacity, not it's size. (The vector's capacity tells up to which size the vector can grow without needing to re-allocate and copy all members. Basically it's only there for optimization purposes.) You cannot access any members in result after that reservation, since there aren't any. Either use result.push_back(...) instead of result[dp] = ... or result.resize(a.size()) instead of result.reserve(a.size()).
I suppose the former could be more effective.
One problem is with the usage of reserve() (either use resize() or append items with push_back() instead of accessing the index).
if (a.size() == 1) return a;
int middle = a.size() / 2;
vector<int>::const_iterator first = a.begin();
vector<int>::const_iterator mid = a.begin() + (middle - 1);
vector<int>::const_iterator last = a.end();
vector<int> ll(first, mid);
vector<int> rr(mid, last);
This could be another problem. If the size is 2, then ll would end up being an empty vector, and this function doesn't appear to handle this. There doesn't seem to be much reason to subtract 1 from middle anyway.
It is also possible that you are copying things around far more than needed: you shouldn't need the l and r vectors (because they will just be copies of ll and rr), similarly I don't think you need the result vector, since you could just write the merged results right back to a.
reserve() does not change the amount of contents in the vector. You've created an empty vector, reserved a certain size for it, and then used v[i] = x; This is not a valid use of vector since there still isn't any i'th element in the vector.
Use resize() instead.
The error message is very unclear, because it is the standard message of VC++ when an exception goes unhandled. You could add a try-catch-clock to your main to get the exception and a more meaningful error:
int main() {
try {
// do main stuff here
}
catch ( std::exception & e ) {
std::cout << e.what() << std::endl;
}
}
This is for the command-line. If your application doesn't have one, use a message box or write the error to a log-file.
With regard to the problem in your code, all the other answers appear to be correct.

Find which numbers appears most in a vector

I have some numbers stored in a std::vector<int>. I want to find which number appears most in the vector.
e.g. in the vector
1 3 4 3 4 2 1 3 2 3
the element that occurs the most is 3.
Is there any algorithm (STL or whatever) that does this ?
Sort it, then iterate through it and keep a counter that you increment when the current number is the same as the previous number and reset to 0 otherwise. Also keep track of what was the highest value of the counter thus far and what the current number was when that value was reached. This solution is O(n log n) (because of the sort).
Alternatively you can use a hashmap from int to int (or if you know the numbers are within a limited range, you could just use an array) and iterate over the vector, increasing the_hashmap[current_number] by 1 for each number. Afterwards iterate through the hashmap to find its largest value (and the key belonging to it). This requires a hashmap datastructure though (unless you can use arrays which will also be faster), which isn't part of STL.
If you want to avoid sorting your vector v, use a map:
int max = 0;
int most_common = -1;
map<int,int> m;
for (vi = v.begin(); vi != v.end(); vi++) {
m[*vi]++;
if (m[*vi] > max) {
max = m[*vi];
most_common = *vi;
}
}
This requires more memory and has a very similar expected runtime. The memory required should be on the order of a full vector copy, less if there are many duplicate entries.
Try this
int FindMode(vector<int> value)
{
int index = 0;
int highest = 0;
for (unsigned int a = 0; a < value.size(); a++)
{
int count = 1;
int Position = value.at(a);
for (unsigned int b = a + 1; b < value.size(); b++)
{
if (value.at(b) == Position)
{
count++;
}
}
if (count >= index)
{
index = count;
highest = Position;
}
}
return highest;
}
This is how i did it:
int max=0,mostvalue=a[0];
for(i=0;i<a.size();i++)
{
co = (int)count(a.begin(), a.end(), a[i]);
if(co > max)
{ max = co;
mostvalue = a[i];
}
}
I just don't know how fast it is, i.e. O() ? If someone could calculate it and post it here that would be fine.
Here is an O(n) generic solution for finding the most common element in an iterator range. You use it simply by doing:
int commonest = most_common(my_vector.begin(), my_vector.end());
The value type is extracted from the iterator using iterator_traits<>.
template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
T most_common(InputIt begin, InputIt end)
{
std::map<T, int> counts;
for (InputIt it = begin; it != end; ++it) {
if (counts.find(*it) != counts.end()) {
++counts[*it];
}
else {
counts[*it] = 1;
}
}
return std::max_element(counts.begin(), counts.end(),
[] (const std::pair<T, int>& pair1, const std::pair<T, int>& pair2) {
return pair1.second < pair2.second;})->first;
}