Unable to understand error - c++

I have written a mergesort algo as follows but on compiling it I get the following ,which states
Expression: vector subscript out of range
I dont understand why I am getting this error, plz point out the mistakes,I have coded this algo based on my understanding of the mergesort algorithm
As per my understanding I have coded a recursive function(mergesort), in which each time the array in question is divided in two parts left and right namely and then the left and right arrays are subdivided further till the point where there is only 1 element present in the subarrays once this stage arrives the merge function is called to sort the partitioned arrays and merge it to the original array from which the arrays were partitioned and the recursion goes a step backward in the recursion tree
Here is the source code
#include<iostream>
#include<vector>
using namespace std;
class Soham
{
vector<int> v;
public:
Soham();
void merge(vector<int> &, vector<int> & ,vector<int> &);
void mergesort(vector<int> &);
};
Soham::Soham()
{
int no;
for (int i = 0; i < 5; i++)
{
cin >> no;
v.push_back(no);
}
mergesort(v);
cout << "result" << endl;
for (auto it = v.begin(); it != v.end(); it++)
cout << *it << " ";
}
void Soham::mergesort(vector<int> &v)
{
if (v.size() < 2)
return;
else
{
vector<int>left, right;
if (v.size() % 2 == 0)//if input size is even
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),it);
right.assign(it, v.end());
}
else// if input size is odd
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),next(it));
right.assign(next(it), v.end());
}
mergesort(left);
mergesort(right);
merge(left, right,v);
}
}
void Soham::merge(vector<int> &temp_left, vector<int> &temp_right,vector<int> &temp_main)
{
int i = 0, j = 0, k = 0;
while (i<= temp_left.size() && j <= temp_right.size())
{
if (temp_left[i] <= temp_right[j])
{
temp_main[k] = temp_left[i];
i++;
k++;
}
else
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
while (i <= temp_left.size())
{
temp_main[k]=temp_left[i];
i++;
k++;
}
while (j <= temp_right.size())
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
int main()
{
Soham a;
system("pause");
return 0;
}
Thanks For Help

while (i <= temp_left.size())
When you access vector at index size() you will get your out-of-bounds access

Related

How to change this backtracking code into a dynamic programming code by using memoization?

I'm trying to learn dynamic programming and hence I'm trying to solve UVA 11450. Since I know I could solve this question using backtracking, I decided to solve it using backtracking and then add memoization to the code. However, I'm unable to do this.
Here is the commented code without memoization:
#include <bits/stdc++.h>
using namespace std;
bool b; // this tells us if a solution is found or not
int c; // store input c
vector <vector <int>> arr; // declare a global array to store the type and cost of the garments
int money = INT_MAX; // these two fields store the most optimal solution found so far
vector <int> garr;
// this function fills 'c' - the candidates for the k'th postition
void construct_candidates(vector <int> &a, int k, int m, vector<int> &c)
{
for (int i: arr[k])
{
if (i <= m ) c.push_back(i); // if cost of the model 'i' of garment 'k' is less than or equal to money remaining,
} // put it in array 'c'.
}
void backtrack(vector <int> &a, int k, int m)
{
vector <int> c; // this array stores the candidates for postion k.
if (k == a.size() - 1) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
int main()
{
int n;
cin >> n;
while (n--)
{
b = false; // initialising global variables
money = INT_MAX;
arr.clear();
int m;
cin >> m >> c;
arr = vector <vector <int>>(c);
for(int i = 0; i < c; i++) // storing the input in arr
{
int k;
cin >> k;
arr[i] = vector <int> (k);
for (int j = 0; j < k; j++)
{
cin >> arr[i][j];
}
}
vector <int> a(c, -1); // the backtracking code will attempt
//to fill this array with optimal garments
backtrack(a, -1, m);
if (b) cout <<m - money << endl;
else cout << "no solution" << endl;
}
return 0;
}
Now, to add memoization, I tried doing:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
if (dp[k][m] != -1) // this is
{ // the
k++; // part
a[k] = dp[k][m]; // that
backtrack(a, k, m - a[k]); // is
} // added
else
{
vector <int> c;
if (k == a.size() - 1)
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else
{
k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}
But I don't know where or how to add the part that actually puts the optimal garment at position k in the DP table. Any help is much appreciated.
Thanks to the very helpful comment by #AlexanderZhang, I have solved the question. Refer to his comment for the details if interested. Here is the code:
vector <vector <int>> dp(20, vector<int> (201, -1));
void backtrack(vector <int> &a, int k, int m)
{
k++;
if (dp[k][m] != -1)
{
return;
}
else
{
dp[k][m]++;
vector <int> c; // this array stores the candidates for postion k.
// for (int kj : a) cout << kj << " ";
// cout << endl;
if (k == a.size() ) // if (is_a_soln) process_solution
{
if (m < money)
{
b = true;
money = m;
garr = a;
}
}
else // else backtrack with updated parameters
{
// k++;
construct_candidates(a, k , m, c);
for (int i = 0; i < c.size(); i++)
{
a[k] = c[i];
backtrack(a, k, m - c[i]);
}
}
}
}

Finding two associated indexes where the sum of two elements equals a target value

Background:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
Question:
I have a list of numbers 1,2,3,4,5. My target value is 8, so I should return indices 2 and 4. My first thought is to write a a double for loop that checks to see if adding two elements from the list will get my target value. Although, when checking to see if there is such a solution, my code returns that there is none.
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(5);
int target = 8;
string result;
for(int i = 0; i < list.size(); i++) {
for(int j = i+1; j < list.size(); j++) {
if(list[i] + list[j] == target) {
result = "There is a solution";
}
else {
result = "There is no solution";
}
}
}
cout << result << endl;
return 0;
}
Perhaps my approach/thinking is plain wrong. Could anyone provide any hints or suggestions to solving this problem?
Your approach is correct but you are forgetting you are in a loop that continues after finding the solution.
This will get you halfway there. I recommend putting both loops in a function, and returning once you find a match. One thing you could do is return a pair<int,int> from that function or you could simply output the results from within that point in the loop.
bool solutionFound = false;
int i,j;
for(i = 0; i < list.size(); i++)
{
for(j = i+1; j < list.size(); j++)
{
if(list[i] + list[j] == target)
{
solutionFound = true;
}
}
}
Here is what the function approach might look like:
pair<int, int> findSolution(vector<int> list, int target)
{
for (int i = 0; i < list.size(); i++)
{
for (int j = i + 1; j < list.size(); j++)
{
if (list[i] + list[j] == target)
{
return pair<int, int>(i, j);
}
}
}
return pair<int, int>(-1, -1);
}
int main() {
vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(5);
int target = 8;
pair<int, int> results = findSolution(list, target);
cout << results.first << " " << results.second << "\n";
return 0;
}
Here's the C++ incorporating Dave's answer for linear execution time and a couple helpful comments:
pair<int, int> findSolution(vector<int> list, int target)
{
unordered_map<int, int> valueToIndex;
for (int i = 0; i < list.size(); i++)
{
int needed = target - list[i];
auto it = valueToIndex.find(needed);
if (it != valueToIndex.end())
{
return pair<int, int>(it->second, i);
}
valueToIndex.emplace(list[i], i);
}
return pair<int, int>(-1, -1);
}
int main()
{
vector<int> list = { 1,2,3,4,5 };
int target = 10;
pair<int, int> results = findSolution(list, target);
cout << results.first << " " << results.second << "\n";
}
You're doing this in n^2 time. Solve it in linear time by hashing each element, and checking each element to see if it's complement wrt. the total you're trying to achieve is in the hash.
E.g., for 1,2,3,4,5, with a target of 8
indx 0, val 1: 7 isn't in the map; H[1] = 0
indx 1, val 2: 6 isn't in the map, H[2] = 1
indx 2, val 3: 5 isn't in the map, H[3] = 2
indx 3, val 4: 4 isn't in the map, H[4] = 3
indx 4, val 5: 3 is in the map. H[3] = 2. Return 2,4
Code, as requested (Ruby)
def get_indices(arr, target)
value_to_index = {}
arr.each_with_index do |val, index|
if value_to_index.has_key?(target - val)
return [value_to_index[target - val], index]
end
value_to_index[val] = index
end
end
get_indices([1,2,3,4,5], 8)
Basically the same as zzxyz's most recent edit but a little quicker and dirtier.
#include <iostream>
#include <vector>
bool FindSolution(const std::vector<int> &list, // const reference. Less copying
int target)
{
for (int i: list) // Range-based for (added in C++11)
{
for (int j: list)
{
if (i + j == target) // i and j are the numbers from the vector.
// no need for indexing
{
return true;
}
}
}
return false;
}
int main()
{
std::vector<int> list{1,2,3,4,5}; // Uniform initialization Added in C++11.
// No need for push-backs of fixed data
if (FindSolution(list, 8))
{
std::cout << "There is a solution\n";
}
else
{
std::cout << "There is no solution\n";
}
return 0;
}

reduce the complexity of the program

Here is the program to find the pairs that sums up to 3.
For example:
INPUT : 0,3,5,1,2,4
OUTPUT: 0,3,1,2.
That means it should return all the pairs whose sum is equal to 3.
But I want to reduce the time complexity of this program. Right now I am using two nested for loops.
Can anyone suggest a better method to reduce the time complexity.
#include<iostream>
#include <vector>
using namespace std;
void main()
{
vector<int> v;
vector<int> r;
int x;
cout << "Enter the elements";
for(int i = 0; i < 6; i++)
{
cin >> x;
v.push_back(x);
}
for(int i = 0 ; i < v.size() - 1; i++)
{
for(int j = i + 1; j < v.size(); j++)
{
if(v[i] + v[j] == 3)
{
r.push_back(v[i]);
r.push_back(v[j]);
}
}
}
cout << "\noutput\n";
for(int i = 0 ; i < r.size(); i++)
{
cout<<r[i]<<"\n";
}
}
I'd do two preparation steps; First, eliminate all numbers > 3, as they will not be part of any valid pair. This reduces the complexity of the second step. Second, sort the remaining numbers such that a single walk through can then find all the results.
The walk through approaches the pairs from both ends of the sorted array; if a pair is found, both bounds can be narrowed down; if the current endings do sum up to a value > 3, only one boundary is narrowed.
Runtime complexity is O(N logN), where N is the count of elements <= 3; O(N logN) basically comes from sorting; the two single walk throughs will not count for large Ns.
int main(int argc, char* argv[]) {
const int N = 3;
std::vector<int> input{ 0,3,5,1,2,4};
std::vector<int>v(input.size());
int t=0;
for (auto i : input) {
if (i <= N) {
v[t++]=i;
}
}
std::sort (v.begin(), v.end());
long minIdx = 0;
long maxIdx = v.size()-1;
while (minIdx < maxIdx) {
int minv = v[minIdx];
int maxv = v[maxIdx];
if (minv+maxv == 3) {
cout << minv << '+' << maxv << endl;
minIdx++;maxIdx--;
}
else
minIdx++;
}
return 0;
}
You are searching for all the combinations between two numbers in n elements, more specifically, those that sum up to specific value. Which is a variation of the subset sum problem.
To make this happen you could generate all combinations without repetitions of the indexes of the vector holding the values. Here is an example of how to do this recursively and here is an example of how to do it iteratively, just to get an idea and possibly use it as a benchmark in your case.
Another approaches are dynamic programming and backtracking.
Late answer but works for negative integers too... For first, find the smallest number in the std::vector<int>, then like this answer says, remove all elements (or copy the opposite), which are higher than 3 + minimum. After sorting this std::vector<int> iterate through it from both ends with condition shown bellow:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
std::vector<int> findPairs(const std::vector<int>& input, const int sum) {
int minElem = INT_MAX;
for(auto lhs = input.begin(), rhs = input.end() - 1; lhs < rhs;
++lhs, --rhs) {
const int elem = (*lhs < *rhs ? *lhs : *rhs);
if(elem < minElem)
minElem = elem;
}
std::vector<int> temp(input.size());
const auto tempBegin = temp.begin();
const auto tempEnd = std::remove_copy_if(input.begin(), input.end(),
temp.begin(), [minElem, sum](int elem) {
return (elem + minElem) > sum;
});
std::sort(tempBegin, tempEnd);
std::vector<int> result;
auto leftIter = tempBegin;
auto rightIter = tempEnd - 1;
while(leftIter < rightIter) {
if(*leftIter + *rightIter == sum) {
result.push_back(*leftIter++);
result.push_back(*rightIter--);
}
else {
if(sum - *leftIter < *rightIter) rightIter--;
else leftIter++;
}
}
return result;
}
int main() {
auto pairs = findPairs({ 0, 3, 5, 1, 2, 4, 7, 0, 3, 2, -2, -4, -3 }, 3);
std::cout << "Pairs: { ";
for(auto it = pairs.begin(); it != pairs.end(); ++it)
std::cout << (it == pairs.begin() ? "" : ", ") << *it;
std::cout << " }" << std::endl;
}
The code above will results the following:
Pairs: { -4, 7, -2, 5, 0, 3, 0, 3, 1, 2 }
I think you can solve this in O(n) with a map.
public void printPairs(int[] a, int v)
{
map<int, int> counts = new map<int, int>();
for(int i = 0; i < a.length; i++)
{
if(map.count(a[i]) == 0)
{
map[a[i]] = 1;
}
else
{
map[a[i]] = map[a[i]] + 1;
}
}
map<int, int>::iterator it = map.begin();
while(it != map.end())
{
int v1 = it->second;
if (map.count(v - v1) > 0)
{
// Found pair v, v1
//will be found twice (once for v and once for v1)
}
}
}

How can I sort array elements by number of divisors?

My problem is that I hit an obstacle while I was solving some exercises.
The source of the problem is that I have to write a program which sort descending an array by the number of each element's divisors, but when two element has the same number of divisors it should sort ascending those values.
My code so far:
#include <iostream>
#include <fstream>
using namespace std;
int cntDiv(int n) //get number of divisors
{
int lim = n;
int c = 0;
if(n == 1)
return 1;
for(int i = 1; i < lim; i++)
{
if(n % i == 0)
{
lim = n / i;
if(lim != i)
c++;
c++;
}
}
return c;
}
int main()
{
ifstream fin("in.txt");
int n, i, j;
fin >> n;
int v[n];
for(i = 0; i < n; i++)
fin >> v[i];
int div[n];
for(i = 0; i < n; i++)
div[i] = cntDiv(v[i]);
for(i = 0; i < n - 1; i++)
{
for(j = i + 1; j < n; j++)
{
if(div[i] < div[j] && div[i] != div[j]) //if the number of divisors are different
{
int t = v[i];
v[i] = v[j];
v[j] = t;
t = div[i];
div[i] = div[j];
div[j] = t;
}
if(div[i] == div[j] && v[i] > v[j]) //if the number of divisors are the same
{
int t = v[i];
v[i] = v[j];
v[j] = t;
}
}
}
for(i = 0; i < n; i++)
{
cout << v[i] << " ";
}
return 0;
}
In.txt:
5
12 20 4 100 13
Output:
100 12 20 4 13
Although it works fine with this one and many other. For bigger inputs it exceeds the time limit which is 0.1s. Any advice how should I rewrite the sorting? (I wrote bubble sort because I could not implement sorting array by property via quicksort)
Use an array of structures. The structure would contain the original value and a container of divisors:
struct Number_Attributes
{
int number;
std::list<int> divisors;
};
You can then write a custom comparator function and pass to std::sort:
bool Order_By_Divisors(const Number_Attributes& a,
const Number_Attributes& b)
{
return a.divisors.size() < b.divisors.size();
}
The sorting then becomes:
#define ARRAY_CAPACITY (20U)
Number_Attributes the_array[ARRAY_CAPACITY];
//...
std::sort(&array[0], &array[ARRAY_CAPACITY], Order_By_Divisors);
The generation of divisors is left as an exercise for the OP.
Reworking your code with std::sort:
std::vector<std::pair<int, int>> customSort(const std::vector<int>& v)
{
std::vector<std::pair<int, int>> ps;
ps.reserve(v.size());
// We don't have zip sort :/
// So building the pair
for (auto e : v)
{
ps.emplace_back(e, cntDiv(e));
}
std::sort(ps.begin(), ps.end(), [](const auto&lhs, const auto& rhs) {
// descending number of divisors, increasing value
return std::make_tuple(-lhs.second, lhs.first)
< std::make_tuple(-rhs.second, rhs.first);
});
return ps;
}
int main()
{
const std::vector<int> v = {12, 20, 4, 100, 13};
const auto res = customSort(v);
for(const auto& p : res)
{
std::cout << p.first << " ";
}
}
Demo

C++ Assertion Failed on vector at runtime Expression: vector subscript out of range

im gettin this really annoying error message. I know Im only new to this but it seems the type of thing I could figure out. Can anyone show me where im going wrong please?
The message at run time is:
Debug Assertion Failed!
Program:
....
File: c:\program files\microsoft visual studio 10.0\vc\include\vector
Line: 932
Expression: Vector subscript out of range
and the code is
#include "VectorIntStorage.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
void VectorIntStorage::Read(istream& r)
{
char c[13];
r >> c;
r >> NumberOfInts; //gets number of ints for vector
//numberVector = new std::vector<int> numberVector;
for(int i = 0; i < NumberOfInts; i++)
{
r >> numberVector[i];
cout << numberVector[i] << endl;
if(_sortRead) //true
{
for(int k = 0; k < i; k++)
{
if(numberVector[i] < numberVector[k])
{
int temp = numberVector[k];
numberVector[k] = numberVector[i];
numberVector[i] = temp;
}
}
}
}
}
void VectorIntStorage::Write(ostream& w)
{
for(int i = 0; i < NumberOfInts; i++)
{
w << numberVector[i] << endl;
cout << numberVector[i] << endl;
}
}
void VectorIntStorage::sortStd()
{
sort(numberVector.begin(), numberVector.end());
}
void VectorIntStorage::sortOwn()
{
quickSort(0, NumberOfInts - 1);
}
void VectorIntStorage::setReadSort(bool sort)
{
_sortRead = sort;
}
void VectorIntStorage::quickSort(int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = numberVector[(left + right) / 2];
while (i <= j)
{
while (numberVector[i] < pivot)
i++;
while (numberVector[j] > pivot)
j--;
if (i <= j)
{
tmp = numberVector[i];
numberVector[i] = numberVector[j];
numberVector[j] = tmp;
i++;
j--;
}
}
if (left < j)
{
quickSort(left, j);
}
if (i < right)
{
quickSort(i, right);
}
}
VectorIntStorage::VectorIntStorage(const VectorIntStorage& copying)
{
//int *duplicate = new int[(copying.NumberOfInts)];
//vector<int> *duplicate = new vector<int>;
//std::copy(numberVector.begin(), numberVector.end(), duplicate);
//numberVector = duplicate;
//NumberOfInts = copying.NumberOfInts;
}
VectorIntStorage::VectorIntStorage(void)
{
}
VectorIntStorage::~VectorIntStorage(void)
{
}
We don't have enough information to say for sure, but I suspect the failing line is r >> numberVector[i]. I suppose you meant to say int j; r >> j; numberVector.push_back(j);
The problem is precisely what the error message says: your vector subscript (i) is out of range. Specifically, you never increase the size of your vector, so it is always of size 0. Thus, any use of operator[] is going to reference an out-of-range element.
You can't just use numberVector[i] without calling numberVector.resize() first.
vector<int> vec;
vec[1] = 0; // fails - vec is empty so [1] is out of range
vec.resize(100);
vec[1] = 5; // ok, you can access vec[0] .. vec[99] now
vec.push_back(11); // Now the size is 101 elements, you can access vec[0] .. vec[100]
r >> NumberOfInts; //gets number of ints for vector
From the above comment, it seems you need a vector of size NumberOfInts. But leaving the line as commented -
//numberVector = new std::vector<int> numberVector;
You are declaring the vector as -
std::vector<int> numberVector; // The size of the vector is 0
To perform the operation of [] on numberVector, it's size should be mentioned and should be in the valid range while declaration. Since it not mentioned while declaration, you need to do a push_back operation to dynamically increase the size of the vector.
for(int i = 0; i < NumberOfInts; i++)
{
r >> numberVector[i]; // Size isnot initially mentioned while declaration
// of the vector to do an `[]` operation
cout << numberVector[i] << endl;
// ....