So i was trying to make the challage: Breadth First Search: Shortest Reach on HackerRank, but i keep getting the bad alloc exception when the tests have great numbers of node/edges. The program works on the first test, so i don't think, it's something wrong with the implementation.
So here is the implementation:
(sorry for the indentation , my first question)
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <limits.h>
using namespace std;
int main() {
//test numbers
int t;
//the cost
int cost = 6;
cin >> t;
//for each test
for (int nt = 0; nt < t; ++nt) {
int n, e;
int snode;
queue <int> *que = new queue<int>();
//read the node/edges
cin >> n >> e;
//distance/visited/parents arrays/adjlist vector
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
vector< vector<int> > adjList(n + 1);
//read into the adjlist, unoriented graph, each edge has 6 weight
for (int ne = 0; ne < e; ++ne) {
int x, y;
cin >> x >> y;
adjList[x].push_back(y);
adjList[y].push_back(x);
}
//read the starting node
cin >> snode;
dist[snode] = 0;
//do actual bfs
que->push(snode);
visited[snode] = true;
while(!que->empty()) {
int c_node = que->front();
que->pop();
for (int i = 0; i < adjList[c_node].size(); ++i) {
if (visited[adjList[c_node].at(i)] == false) {
que->push(adjList[c_node].at(i));
parents[adjList[c_node].at(i)] = c_node;
dist[adjList[c_node].at(i)] = dist[parents[adjList[c_node].at(i)]] + cost;
visited[adjList[c_node].at(i)] == true;
}
}
}
//print at output the distance from the starting node to each other node
//if unreachable, print -1
for (int i = 1; i < n + 1; ++i) {
if (i == snode) {
} else if (dist[i] == 0 && i != snode) {
cout << "-1 ";
} else {
cout << dist[i] << " ";
}
}
cout << "\n";
}
return 0;
}
Am i doing something wrong, i haven't seen anyone else complain on this matter in the discussion section of the site.
How can i avoid the exception to be thrown and from where does it come?
Thank you!
I don't know, exactly, what is the cause of your exception; and I don't know ho to reproduce your problem because depends (I suppose) from the input values. A lot of input values, I suppose.
But I see some weak points (IMHO) of your code, so I try to point your attention to them.
1) you alloc a std::queue in your for cycle
queue <int> *que = new queue<int>();
but you never free it; it's a waste of memory
2) you're using C-style variable-length arrays
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
They aren't valid C++ standard code. I suggest you the use of standard containers (std::vector or std::queue).
3) you're initializing your C-style variable-length arrays with a initializers lists with only an element (-1 or false). I suppose your intention was initialize all n+1 elements with -1 and false. But this syntax initialize only the first element of the array with -1 and false.
If you want to initialize all n+1 element to -1 and false, the solution is (again) use standard containers; by example
std::vector<int> dist(n+1, -1);
std::vector<bool> visited(n+1, false);
std::vector<int> parents(n+1, -1);
4) you access arrays without bounds checking. By example:
cin >> snode;
dist[snode] = 0;
where snode is a int variable; if you insert a negative value, or a value over n, you write dist out of its bounds, devastating the memory. This, I suppose, can explain your "bad alloc exception".
Suggestion: use standard containers (again) instead of C-style array and use at() (that perform bounds checking) instead []; so
cin >> snode;
dist.at(snode) = 0;
5) sorry for my bad English (ok, I'm joking: this isn't one of your weak points; this is one of mine).
Related
I'm writing code for a dynamic solution to the knapsack problem, with the values, weight, etc being read in from a file. After writing the knapsack function code, it seems that it will not return when I try to test just the result being returned.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
//knapsack here
int knapsack(int cap, int weight[], int value[], int n)
{
int** K = new int* [n + 1];
int j = 0;
int l = 0;
for (int i = 0; i < n + 1; i++)
{
K[i] = new int[cap + 1];
}
for (j = 0; j <= n; j++)
{
for (l = 0; l <= cap; l++)
{
if (j == 0 || l == 0)
K[j][l] = 0;
else if (weight[j - 1] <= l)
{
K[j][l] = max(weight[j - 1] + K[j - 1][l - weight[j - 1]], K[j - 1][l]);
}
else
{
K[j][l] = K[j - 1][l];
}
}
}
return K[j][l]; <--- Exception thrown
}
int main(void)
{
string filename;
ifstream infile;
int capacity = 0;
int items = 0;
//Get input file from user and open
cout << "Enter the file name: ";
cin >> filename;
infile.open(filename);
//Get capacity and number of items
infile >> capacity >> items;
//Initialize arrays
int* w = new int[items];
int* v = new int[items];
//Read values from file into arrays
for (int i = 0; i < items; i++)
{
infile >> w[i];
infile >> v[i];
}
//Solution Table
cout << endl << endl << endl;
cout << "Solution Table:" << endl;
//Testing purposes
cout << knapsack(capacity, w, v, items) << endl << "Test";
infile.close();
return 0;
}
Everything that is printed in main will print up until the final cout (after the Solution Table: line prints). The program will then pause for a moment and exit with an error code (C:\Users\Me\source\repos\Project3\Debug\Project3.exe (process 3028) exited with code -1073741819). I haven't been able to figure out a way to get a return from the function yet, and the exiting is something I haven't been able to figure out why it is occurring either.
EDIT: On using the debugger, an exception is being thrown when running through the knapsack function on the return:
Exception thrown at 0x006BB128 in Project3.exe: 0xC0000005: Access violation reading location 0xFDFDFE0D
int** K = new int* [n + 1];
// ...
K[i] = new int[cap + 1];
// ...
for (j = 0; j <= n; j++)
{
for (l = 0; l <= cap; l++)
{
// ...
}
}
// j == n + 1
// l == cap + 1
return K[j][l]; <--- Exception thrown because of out of bounds access to K
K is an array of length n + 1, which means its elements are accessed using indices from O to (inclusive) n. n + 1 is an out of bound access. At the end of the (outer) for loop the variable j is n + 1. You make the same error with the inner loop and the second operator[].
That being said, it helps a lot if you:
Ditch the idea of "2d arrays". These arrays of pointers to arrays are difficult to handle and have a heavy performance impact (messed up memory locality). They are (probably) only useful when the "full" array (e.g. the 2D table flattened into a single array) is too large to reliably get successfully allocated.
Use std::vector. There is really no point working with raw arrays. Except for learning. And in that case: delete[] the memory you allocate!
Why is "using namespace std;" considered bad practice?
C-style strings might cause problems. They are hard to maintain and track. I support Jesper's idea here.
Also, I do not see that you are freeing the memory after you are done with the pointers which will create memory leakage.
I ran a few tests of a simple problem in both VS 19 and CodeBlocks after an error that keeps popping in a lot of my coding problems. Surprisingly in Codeblocks everything runs fine and i get the expected result while in VS i always get the "vector subscript out of range" error.
The problem is quite simple, get the least number of stops until the destination. (just count them)
The error appears at the second while loop where i compare i to the size of the vector.
I am wondering why it actually works in codeblocks and also would like to know how to fix it in VS
#include <iostream>
#include <vector>
using namespace std;
int compute_min_refills(int dist, int tank, vector<int>& stations) {
int distanceTraversed = 0;
int i = 0;
int stops = 0;
bool impossible = false;
while (distanceTraversed<=dist)
{
if((distanceTraversed + tank)> dist)
{
distanceTraversed = dist;
return stops;
}
while ((distanceTraversed + tank) > stations[i] && i< stations.size())
{
i++;
impossible = false;
}
if ((distanceTraversed + tank) <= stations[i] || i == stations.size())
{
if (impossible == true)
{
return -1;
}
else
{
distanceTraversed += stations[i - 1];
stops++;
impossible = true;
}
}
}
return stops;
}
int main() {
int d = 0;
cin >> d;
int m = 0;
cin >> m;
int n = 0;
cin >> n;
vector<int> stations;
int a;
for (int i = 0; i < n; ++i)
{
cin>>a;
stations.push_back(a);
}
cout << compute_min_refills(d, m, stations) << "\n";
return 0;
}
Here are some imputs if you want to test this out:
Input:
500
200
4
100 200 300 400
You're bound checking your vector accesses too late.
Because of short-circuit evaluation, (distanceTraversed + tank) > stations[i] && i< stations.size() doesn't work the way you think it does, 1st you access the array, and only if the condition was true, you check if the access was inside bounds, which is UB if it was not.
Later on (distanceTraversed + tank) <= stations[i] || i == stations.size() doesn't check for bounds either.
And as a final note, distanceTraversed += stations[i - 1]; if i==0, you will try to access element -1, but std::vector is indexed using std::size_t which is unsigned, causing an implicit conversion, an assigning very large value to it.
Hi I'm trying to solve a algorithm problem and when I submit my code on an online judge I keep on getting a runtime error. I have no idea why it is happening.
Here is the problem that I'm trying to solve.
The code is as follows. It works fine for the sample input and outputs in visual studio. I haven't yet met inputs and outputs that does not work well or actually meet the runtime error. Only the online judge is giving the runtime error so I can't figure out why.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int m;
int c1;
int c2;
cin >> n >> m >> c1 >> c2;
vector<int> p = {};
vector<int> q = {};
for (int i = 0; i < n; ++i)
{
int temp;
cin >> temp;
p.push_back(temp);
}
for (int i = 0; i < m; ++i)
{
int temp;
cin >> temp;
q.push_back(temp);
}
vector<int> distance = {};
for (int i = 0; i < p.size(); ++i)
{
for (int j = 0; j < q.size(); ++j)
{
distance.push_back(abs(p[i] - q[j]) + abs(c1 - c2));
}
}
sort(distance.begin(), distance.end());
int min = distance[0];
int count = 0;;
for (int i = 0; i < static_cast<int>(distance.size()); ++i)
{
if (distance[0] == distance[i])
count++;
else
break;
}
cout << min << " " << count << endl;
return 0;
}
If n and m are both the maximum allowed value of 500,000 then distance will have 500,000 * 500,000 elements which will use 1TB of memory. Due to vector growing as you push_back you could actually need around 2TB of memory in total. The online judge presumably doesn't allow you to use this much memory.
If you rethink your algorithm to not store the values of distance it will probably work.
You should lways use reserve on std::vector if you know the size in advance as it should cause the vector to allocate exactly the right amount of memory and avoid copying to new blocks of memory as the vector grows.
TL;DR: My code is "fast" in Java but slow as hell in C++. Why?
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int read(string data, int depth, int pos, vector<long>& wantedList) {
// 91 = [
if (data.at(pos) == 91) {
pos++;
// Get first part
pos = read(data, depth + 1, pos, wantedList);
// Get second part
pos = read(data, depth + 1, pos, wantedList);
} else {
// Get the weight
long weight = 0;
while (data.length() > pos && isdigit(data.at(pos))) {
weight = 10 * weight + data.at(pos++) - 48;
}
weight *= 2 << depth;
wantedList.push_back(weight);
}
return ++pos;
}
int doStuff(string data) {
typedef map<long, int> Map;
vector<long> wantedList;
Map map;
read(data, 0, 0, wantedList);
for (long i : wantedList) {
if (map.find(i) != map.end()) {
map[i] = map[i] + 1;
} else {
map[i] = 1;
}
}
vector<int> list;
for (Map::iterator it = map.begin(); it != map.end(); ++it) {
list.push_back(it->second);
}
sort(list.begin(), list.begin() + list.size());
cout << wantedList.size() - list.back() << "\n";
return 0;
}
int main() {
string data;
int i;
cin >> i;
for (int j = 0; j < i ; ++j) {
cin >> data;
doStuff(data);
}
return 0;
}
I have just tried my first C++ project, and it's re-written code from Java.
The original task was to calculate how many numbers that needed to be changed in order to "balance" the input, given that each level above something weighs double the lower
eg [1,2] would need 1 change (either 1->2 or 2->1 in order to be equal on both sides and [8,[4,2]] would need 1 change (2->4) in order for the "lower level" to become 8 and therefore be of equal weight on the higher level. The problem can be found here for those who are interested:
Problem link
And for those who wonder, this is a school assignment regarding algorithms, but I'm not asking for help with that, since I have already completed it in Java. The problem is that my algorithm seem to be pretty shit when it comes to C++.
In Java I get times around 0.6 seconds, and in C++, the "same" code gives >2 seconds (time limit exceeded).
Anyone care to give me a pointer as to why this is? I was under the impression that C++ is supposedly faster than Java when it comes to these type of problems.
One of possible reasons is copying.
Whenever you pass something by value in C++ a copy is created. For tings like double, int or a pointer, that's not a problem.
But for objects like std::string copying may be expensive. Since you don't modify data it makes sense to pass it by const reference:
int read(const string &data, int depth, int pos, vector<long>& wantedList)
So I wanted to clean the rust off my C++ skills and thought I'd start with something fairly simple. An equilibrium point in a vector A of size N is a point K, such that: A[0] + A[1] + ... + A[K−1] = A[K+1] + ... + A[N−2] + A[N−1]. The rationale behind the function algorithm is simple: Check each consecutive element of the vector and compare the sum of the elements before said element with the sum of the elements after it and if they are equal, output the index of that element. While it sounds simple (and I imagine that it is) it turned out to be harder to implement in reality. Here's what the code looks like:
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
void EquilibriumPoint(std::vector<int> &A);
void VectorPrint(std::vector<int> &V);
void main()
{
int input;
std::vector<int> Vect1;
cout << "Input the vector elements" << endl;
while (cin >> input)
Vect1.push_back(input);
VectorPrint(Vect1);
EquilibriumPoint(Vect1);
}
void EquilibriumPoint(std::vector<int> &A)
{
for (int it = 0; it != A.size(); ++it)
{
int lowersum = 0;
int uppersum = 0;
for (int beg = 0; beg != it; ++beg) lowersum += A[beg];
for (int end = it + 1; end != A.size(); ++end) uppersum += A[end];
if (uppersum == lowersum) cout << it;
}
}
void VectorPrint(std::vector<int> &V)
{
for (int i = 0; i != V.size(); ++i)
cout << V[i] << endl;
}
As you can see I threw in a print function also for good measure. The problem is that the program doesn't seem to execute the EquilibriumPoint function. There must be a problem with the logic of the implementation but I can't find it. Do you guys have any suggestions?
cin >> input
always returns true for you - so IMHO you have an endless loop. You need to stop collecting elements at some point, for instance
int input = 1
while (input)
{
cin >> input;
Vect1.push_back(input);
}
Will accept all elements that are not zero, when zero arrives, it will end the vector and run your function.
Or you can first input the number of elements (if you want to include zeros), example:
int count;
cin >> count
for (int i = 0; i < count; ++i)
{
cin >> input;
Vect1.push_back(input);
}
I didn't check the rest of the code, though. One problem at a time.