Strange output with large vectors - c++

I was solving AMR10G problem on spoj. The problem is just about sorting and is trivial to implement with arrays. I'm a beginner in STL and just to get familiar with STL i was trying to solve it with using some vectors. The code runs fine with small sizes of vector but with large sizes( can be 20,000 in the problem) it prints all 0s. Here is my code.
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
using namespace std;
int main() {
int T;
cin>>T;
while(T--){
int N, k, i;
cin>>N >> k;
//***********************************************************
vector<int> ar(N);//problem seems to be here when N ~ 20000
//***********************************************************
for(i = 0; i<N; i++) scanf("%d",&ar[i]);
sort(ar.begin(),ar.end());
//calculate smallest difference
int small = ar[k-1] - ar[0];
for(i = k-1; i<N; i++){
int temp;
if( temp = ar[i] - ar[i-k+1] < small) small = temp;
}
cout<<small <<endl;//print smallest difference
}
return 0;
}
When I changed the type to array it ran perfectly fine. What is the problem with using vectors?

Your code has a lack of error checking:
Check that cin >> N >> k succeeded.
Check that each scanf succeeded.
Check k -1 is within range of the array bounds.
Any of those failures could cause your problem.
There is also a logic error on this line:
if( temp = ar[i] - ar[i-k+1] < small) small = temp;
The control expression is parsed as temp = (ar[i] - ar[i-k+1] < small), so this line will set small = 1 if ar[i] - ar[i-k+1] < small and do nothing otherwise. You probably meant (temp = ar[i] - ar[i-k+1]) < small).

Related

Limit on array size

I wrote the following code in c++ which was supposed to print as well as calculate all the prime numbers till n.
The code is perfectly working for n<=10000 but is not working for n>=100000.
#include "iostream"
#include "vector"
using namespace std;
int main(){
int n,ans=0;
cin>>n;
vector <bool> v(n+1,true);
for(int i=2;i<=n;i++){
if(v[i]){
cout<<i<<endl;
ans++;
for(int j=i*i;j<=n;j+=i)
v[j]=false;
}
}
cout<<endl<<ans;
return 0;
}
Kindly state the reason.
Thank you.
In your inner look, j=i*i will overflow a 32-bit signed integer at around 46341. The easiest fix there is to use a long long for j and also cast i correctly before multiplication.
So, change the inner loop to
for (auto j = static_cast<long long>(i) * i; j <= n; j += i)
And that should be it.
As a side note, please don't #include standard headers with double quotes; prefer <vector> and <iostream>.
UPDATE: As a more robust way of doing the same thing (and still using roughly the same code,) I'd suggest the following:
#include <iostream>
#include <vector>
using namespace std;
int main(){
size_t n, ans = 0; // A) Switch to size_t, which can accommodate the largest
// size of a vector; if your number is larger, then we
// can't make an array for it...
cin >> n;
vector<bool> v (n, true); // B) Remove the chance of overflow; indices are
// now shifted by one
for(size_t i = 2; i <= n; i++) {
if (v[i - 1]) {
cout << i << endl;
ans++;
if (n / i >= i) { // C) Check for possibility of overflow in `i*i`
// D) Switch j to correct type
// E) Check if `j+=i` overflowed
for (size_t j = i * i; j <= n && j > i; j += i)
v[j - 1] = false;
}
}
}
cout << endl << ans;
return 0;
}
The really important changes are A, C, and D. The other two, B and E are needed for complete correctness, but they only matter when you have enough actual memory in your system to almost overflow size_t (otherwise, the ctor for vector would throw.) This is completely probably on 32-bit systems, but impossible on 64-bit builds for now.
Also note that A, B, and D are "essentially" free (perf-wise,) but C and E do have some impact on running time (although probably tiny; E is the more onerous.)

How can I print prime numbers till 10^8 using Sieve?

I have recently learnt Sieve algorithm and started to play with it to learn how to use the algorithm in problems. I have written the code correctly as I can't find any bugs in it, but it closes without showing any output. Can't find what's wrong. Help would be appreciated.
#include <iostream>
#include <vector>
//#define MAX 10000
typedef long long int ll;
using namespace std;
vector <ll> primes;
void sieve(){
ll MAX = 100000000;
bool isPrime [MAX];
for(ll i = 0;i < MAX; ++i)isPrime[i] = true;
//isPrime[0] = isPrime[1] = false;
for(ll i=3; i*i <= MAX; i += 2){
if(isPrime[i]){
for(ll j = i*i; j <= MAX; j += i){
isPrime[j] = false;
}
}
}
primes.push_back(2);
for(ll i = 3; i <= MAX; i += 2){
if(isPrime[i]){
primes.push_back(i);
}
}
for(ll i = 0; i <= 10; ++i){
cout<<primes[i]<<endl;
}
}
int main(){
sieve();
return 0;
}
You are creating a static array of size 10^8, which is stored on the stack. This is too large for the stack, and will likely cause a stack overflow.
Instead, use a vector that stores the data on the heap, like this:
vector<bool> isPrime(MAX+1);
Here's a demo.
Also, note that you have an off by one error, since you are indexing at the index MAX, so the vector should be size MAX+1.
Also, you should avoid using namespace std;, as well as typedefs like ll, they make the code harder to read.

How to find the minimun of an array?

I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.

c++ runtime error when using vectors push back and iterator

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.

how can we do n nested for loops where n is dynamic [duplicate]

This question already has answers here:
c++ : dynamic number of nested for loops (without recursion)
(3 answers)
Closed 6 years ago.
I have read the following questions but have not found a solution to my problem:
c++ : dynamic number of nested for loops (without recursion)
variable nested for loops
actual problem statement is :-
Job and Jimmy both are playing with numbers. Job gives Jimmy an array of numbers and asks him to tell the minimum possible last number of a non decreasing sequence of length L.
Input Format
First input line consists of a number which is size of array N.
Next line contains N space separated elements of array.
Next line contains length of the non decreasing sequence i.e. L.
Output Format
You have to print the minimum possible last number of a sequence and if their is no non-decreasing sequence of length L, then print -1
Sample Input
7
9 7 2 5 4 11 12
3
Sample Output
11
Explanation
In sample input, possible non-decreasing sequences of length L=3 are (9,11,12) , (7,11,12) , (2,5,11) , (2,4,11) , (2,5,12) , (2,4,12) , (2,11,12) , (5,11,12) , (4,11,12) and the minimum last number is 11 for the sequences (2,5,11) and (2,4,11). Hence, the answer is 11."
my code...
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int fact(int y,int x)
{
static int temp=0;
if(temp==x)
{
temp=0;
return 1;
}
else
{
++temp;
return y*fact((y-1),x);
}
}
int main() {
int num,randmax,n,s,q,w last=-1, minlast=-1;
cin>>n;
vector<int> a(n);
for(int i=0;i<n; i++)
{
cin>>a[i];
}
cin>>s;
vector<vector<int>> c;
q=fact(s);
c.resize(q);
for(int i = 0 ; i < q ; ++i)
{
//Grow Columns by n
a[i].resize(s);
}
w=q;
randmax=n-1;
int k=0;
while(w)
{
for(int i=0 ; i<n ; i++){
}
num=rand()%randmax; // this works perfect as expected
c[][i]=a[num];
}
w--;
}
/*for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=j+1;k<n; k++)
{
if((a[i]<=a[j])&&(a[j]<=a[k]))
{
last=a[k];
if(minlast=-1)
{
minlast=a[k];
}
if(last<minlast){
minlast=last;
}
}
}
}
}
*/
cout<<last;
return 0;
}
`
I would tell you what I tried to do... I thought of mapping the data by having them randomly assigned in one of my array and then computing them..
I got lost somewhere in my code...plz gimme an solution to it...and more imp. a good explanation of the same as I got stuck at times when I need a dynamic nested n loop type of thing...
also it would be more helpful if you edit in my code or algo so that I could learn where my mistakes are there...
Thanks in advance for you time...
As the answers your links have pointed out, you can imitate a dynamic amount of for loops by using an array David gives a fine implementation here.
For the actual problem you gave though, I see no need for a dynamic amount of for loops at all. The problem is a standard non-decreasing subsequence problem with a slight variation.
#include <iostream>
#include <fstream>
int N, L;
int arr[100], seq[100];
int bst;
int main() {
std::ifstream file ("c.txt");
file >> N;
for(int n = 0; n < N; ++n)
file >> arr[n];
file >> L;
file.close();
bst = 1e9;
for(int i = 0; i <= N; ++i) seq[i] = 1e9;
for(int i = 0; i < N; ++i)
{
int x = 0;
while(seq[x] < arr[i]) ++x;
seq[x] = arr[i];
if(x + 1 >= L)
bst = std::min(bst, arr[i]);
}
std::cout << bst << std::endl;
return 0;
}
This code should solve your problem. The first part does standard parsing and initialization. The rest is a variation on the LIS problem, which has several standard algorithms that solve it. Here, we just check that whenever we extend an array of length L or longer, we see if the element is smaller than our current.