Finding unique element in a long array gives segmentation fault? - c++

I was given a problem to find unique elements in a array formed by using modulo operator over a long integers. So I have written code as:
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
int main(){
long n;
long s;
long p;
long q;
long temp;
long mod= pow(2, 31);
cin >> n >> s >> p >> q;
long array[n];
array[0] = (s % mod);
for(long i = 1; i < n; i++){
temp = array[i-1]*p+q;
array[i] = (temp % mod);
}
set<long> result(array, array + n);
cout << result.size() << endl;
return 0;
}
For smaller input the code runs perfectly fine. When it get tested for input:
100000000 1506922183 1236189611 306853238
It is giving the segmentation fault error.
Where I am going wrong?
Thanks.

long array[n]; is not Standard C++. In addition, given a sufficiently large n it will overrun your Automatic storage and make you have a very bad day. Consider using std::vector<long> array(n); instead.
The math:
long array[n]; with your input resolves to long array[100000000];
long is at least 4 bytes This means you are asking for a minimum of 100000000 * 4 bytes = 400000000 bytes = around 400 MB Automatic Storage.
Typical Automatic data store is a stack of approximately 1-10 MB.

On one side VLA is not legal C++ code, on another you do not need that array at all - you just waste memory:
cin >> n >> s >> p >> q;
set<long> result;
long value = 0;
for(long i = 0; i < n; i++){
value = ( i == 0 ? s : value * p + q ) % mod;
result.insert( value );
}
cout << result.size() << endl;
To speed up you code consider using std::unordered_set instead of std::set

How about this:
vector<long> v;
v.push_back(s % mod);
for (int i = 1; i < n; i++) {
long temp = v[i-1] * p + q;
v.push_back(temp % mod);
}
This way you will not have to define the size of the vector and let it handle it dynamically.

Related

How to solve runtime error in finding the largest number among n numbers

As I'm new to c++ I get runtime error for first example(I mean I tested my program with 5 examples it actually happens automatically by a site for testing) of my program I know that's because of exceeding time for running it but I dunno how to fix this.
My program get n numbers from user and finds the largest one and prints it.
#include<iostream>
#include<curses.h>
using namespace std;
int main()
{
int n;
cin >> n;
int *p = new int(n);
for(int i = 1; i<=n; i++){
cin >> *(p+i);
}
int largest = *p;
for(int i = 1; i<=n; i++){
if(largest < *(p+i))
largest = *(p+i);
}
cout << largest;
return(0);
}
int *p=new int(n);
The line above allocates just a single int, and sets the value to n. It does not allocate an array of n integers.
That line should be:
int *p=new int[n];
And then delete [] p; to deallocate the memory.
But better yet:
#include <vector>
//...
std::vector<int> p(n);
is the preferred way to utilize dynamic arrays in C++.
Then the input loop would simply be:
for(int i=0;i<n; i++)
{
cin >> p[i];
}
That same input loop could have been used if you had used the pointer version.
Then you have this error:
for(int i=1;i<=n;i++)
Arrays (and vectors) are indexed starting from 0 with the upper index at n-1, where n is the total number of elements. That loop has an off-by-one error, where it exceeds the upper index on the last loop.
Basically any loop that uses <= as the limiting condition is suspect. That line should be:
for(int i=0; i<n; i++)
(Note that I changed the code above to fix this error).
However ultimately, that entire loop to figure out the largest can be accomplished with a single line of code using the std::max_element function:
#include <algorithm>
//...
int largest = *std::max_element(p, p + n);
and if using std::vector:
#include <algorithm>
//...
int largest = *std::max_element(p.begin(), p.begin() + n);
I've commented on suggested changes in this slightly modified version:
#include <iostream>
int main()
{
unsigned n; // don't allow a negative amount of numbers
if(std::cin >> n) { // check that "cin >> n" succeeds
int* p=new int[n]; // allocate an array of n ints instead of one int with value n
for(int i=0; i < n; ++i) { // corrected bounds [0,n)
if(not (std::cin >> p[i])) return 1; // check that "cin >> ..." succeeds
}
int largest = p[0];
for(int i=1; i < n; ++i) { // corrected bounds again, [1,n)
if(largest < p[i])
largest = p[i];
}
delete[] p; // free the memory when done
std::cout << largest << '\n';
}
}
Note that using *(p + i) does the same as using p[i]. The latter is often preferred.
This would work if all cin >> ... works, but shows some of the hazards when using raw pointers. If extracting the n ints failes, the program will return 1 and leak the memory allocated with new int[n].
A rewrite using a smart pointer (std::unique_ptr<int[]>) that automatically deallocates the memory when it goes out of scope:
#include <iostream>
#include <memory> // std::unique_ptr
int main()
{
unsigned n;
if(std::cin >> n) {
std::unique_ptr<int[]> p(new int[n]);
for(int i=0; i < n; ++i) { // corrected bounds [0,n)
if(not (std::cin >> p[i])) return 1; // will not leak "p"
}
int largest = p[0];
for(int i=1; i < n; ++i) {
if(largest < p[i])
largest = p[i];
}
std::cout << largest << '\n';
} // p is automatically delete[]ed here
}
However, it's often convenient to store an array and its size together and to do this, you could use a std::vector<int> instead. It comes with a lot of convenient member functions, like, size() - and also begin() and end() which lets you use it in range-based for loops.
#include <iostream>
#include <vector> // std::vector
int main()
{
unsigned n;
if(std::cin >> n) {
std::vector<int> p(n); // a vector of n ints
// a range-based for loop, "elem" becomes a refrence to each element in "p":
for(int& elem : p) {
if(not (std::cin >> elem)) return 1;
}
int largest = p[0];
for(int i = 1; i < p.size(); ++i) { // using the size() member function
if(largest < p[i])
largest = p[i];
}
std::cout << largest << '\n';
}
}
That said, you don't need to store any number in an array to figure out what the largest number is. Instead, just compare the input with the currently largest number.
#include <iostream>
#include <limits> // std::numeric_limits
int main()
{
unsigned n;
if(std::cin >> n) {
// initialize with the smallest possible int:
int largest = std::numeric_limits<int>::min();
while(n--) {
int tmp;
if(not (std::cin >> tmp)) return 1;
if(largest < tmp)
largest = tmp;
}
std::cout << largest << '\n';
}
}

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.

Array of Nodes: Initialization

#include <iostream>
#include <vector>
#include <string>
#include <math.h>
using namespace std;
struct Node{
string data;
Node* next;
Node(){
data = "";
next = NULL;
}
};
int computeHash(string s, int m){
int p = 1000000007;
int x = 263;
unsigned long long sum = 0;
unsigned long long val = 0;
for(int i = 0; i < s.length(); i++){
val = pow(x, i);
sum = (sum + s[i] * val) % p;
}
sum = sum % m;
return sum;
}
int main(){
int buckets;
cin >> buckets;
int n;
cin >> n;
string tag;
string s;
vector< vector<string> > myStore(n);
for(int i = 0; i < n; i++){
cin >> s;
myStore.at(i).push_back(s);
cin >> tag;
myStore.at(i).push_back(tag);
}
Node** arr= new Node*[buckets];
for(int i = 0; i < n; i++){
if(!myStore[i][0].compare("add")){
s = myStore[i][1];
int hash = computeHash(s,buckets);
cout << hash << endl;
}
}
return 0;
}
I am trying to write a program to implement hashing with chains. I am trying to create an array of nodes so that I can append if two strings have the same hash value.
But I am having a problem with the initialization of array of Nodes. I thought the nodes in the array would be pointing to NULL. But when I tried to debug in gdb it is showing some other thing.
Can someone explain where I am wrong on comment about this behavior. Why arr1 and arr[2] are pointing to some memory location instead of null. I also tried to remove the default constructor but still getting the same results. Any help would be appreciated.
You're allocating an array of pointers. Pointers don't have constructors, or default initialization; you're getting random memory (from the allocation).
If you want the array to be NULL-ed out, you need to do so yourself (eg: memcpy, etc.).
You have initialized vector of size n of vectors of size 0 of strings.
Then you want to get the '[1]' (the second element of empty vector of strings)
You have to inutialize them separately.
e.g. in "for" cycle.
Updated. Use myStore.at(i).at(1) instead of myStore[i][1] to achieve checking of boundary conditions. (Try it, you will understand that the problem with vector indeed)

Exceeding memory limit or time limit

I'm attempting to create a program that will multiply 3 not equal positions from vector 1 ('V1'), and find the maximum multiplication.
I'm using 3 'for' loops for counting and writing. The program gets the position amount 'N', then all 'N' numbers in 'input.txt'. After that, it gets the greatest position 'max' and writes it in 'output.exe'.
But I need to keep the program as efficient as possible, 16 MB memory limit and 1 second time limit (I get 1.004 second and 33 MB). Is there a more efficient way to do this?
#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N;
long long max = -9223372036854775807;
int input;
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++)
{
file1 >> V1[i];
}
for (int i = 0; i < N; i++)
for (int j = 0; j < i; j++)
for (int k = 0; k < j; k++)
if (V1[i] * V1[j] * V1[k] > max)
{
max = V1[i] * V1[j] * V1[k];
}
ofstream file2;
file2.open("output.txt");
file2 << max;
file2.close();
}
File Input.txt
5
10 10 10 -300 - 300
From looking at what you have done, you have to find the greatest of the product of 3 numbers in a given input vector.
Just sort vector V1 and output the max of (product of 1st 3 elements or 1st and last 2 elements). This is efficient in both space and time.
Like this:
sort(V1.begin(),V1.end(),greater<int>()) //sorts in descending order
int n = V1.size()-1;
output max(V1[0] * V1[1] * V1[2], V1[0] * V1[n] * V1[n-1])
The first, which comes to my mind - why do you store these values? You only need the single maximum value - there is no need to store all these values, push them, and, moreover, sort them out.
Another important notices:
You have a vector of long long, but you read ints. Since you have big numbers in your input, use long long everywhere
Pushing an item and popping it back is senseless - you should have checked it before pushing to avoid two unnecessary operations
Anyway, you don't need to compare i, j, k for equivalence at all - they are never equal according to your loop restrictions
Pushing items to an array when you know their number is wrong. It takes more time to extend a vector. You may want to resize it to the given size.
Probably, this code will meet your memory \ time requirements:
int N;
long long maximum = -9223372036854775807; // Subject to limits.h LLONG_MIN usage
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++){
file1 >> V1[i];
}
file1.close();
for (int i = 0; i < N; i++)
for (int j = 0; j < i; j++)
for (int k = 0; k < j; k++)
if (V1[i] * V1[j] * V1[k] > maximum)
maximum = V1[i] * V1[j] * V1[k];
ofstream file2;
file2.open("output.txt");
file2 << maximum;
file2.close();
Well, as soon as I see size and time reduction, I tend to remove all unnecessary language goodies, because they do help in proper programming but only come at a resource expense.
So if you really wanted to keep all products of different indices of a list of values, I would advice you to throw away vectors, push and pop and use fixed size arrays.
But before that low-level optimisation, we must think of all possible algorithmic optimisations. You only want be biggest products from all possible from three different values taken from a list. But for positive numbers, a >= b <=> a *c >= b *c and the product of two negative numbers is positive.
So the highest product may only come from:
product of three highest positive values
product of one highest positive value and two lowest negative values (highest in absolute value)
product of three highest negative values if there are no positive values
So you do not even need to load the full initial vector but just keep:
Three highest positive values
Three highest negative values
Two lowest negative values
You get them by storing them at read time in O(n) time and only store eight values. If you only have five values, it is not efficient at all, but it will be linear in time and constant in size whatever number of values you process.
Possible implementation:
#include <iostream>
#include <fstream>
#include <climits>
using namespace std;
class Max3 {
long long pmax[3];
long long nmax[3];
long long nmin[2];
void push(long long *record, long long val, size_t pos) {
for(size_t i=0; i<pos; i++) {
record[i] = record[i + 1];
}
record[pos] = val;
}
void set(long long *record, long long val, size_t sz) {
for (size_t i=1; i<sz; i++) {
if (val < record[i]) {
push(record, val, i - 1);
return;
}
}
push(record, val, sz - 1);
}
public:
Max3() {
size_t i;
for (i=0; i<sizeof(pmax)/sizeof(pmax[0]); i++)
pmax[i] = 0;
for (i=0; i<sizeof(nmin)/sizeof(nmin[0]); i++)
nmin[i] = 0;
for (i=0; i<sizeof(nmax)/sizeof(nmax[0]); i++)
nmax[i] = LLONG_MIN;
}
void test(long long val) {
if (val >= *pmax) {
set(pmax, val, 3);
}
else if (val <= 0) {
if (val <= *nmin) {
set(nmin, -val, 2);
}
if (val >= *nmax) {
set(nmax, val, 3);
}
}
}
long long getMax() {
long long max = 0, prod, pm;
if ((prod = pmax[0] * pmax[1] * pmax[2]) > max)
max = prod;
if (pmax[2] > 0)
pm = pmax[2];
else if (pmax[1] > 0)
pm = pmax[1];
else
pm = pmax[0];
if ((prod = nmin[0] * nmin[1] * pm) > max)
max = prod;
if ((prod = nmax[0] * nmax[1] * nmax[2]) > max)
max = prod;
return max;
}
};
int main() {
int N;
long long input;
Max3 m3;
ifstream file1;
file1.open("input.txt");
file1 >> N;
for (int i = 0; i < N; i++){
file1 >> input;
m3.test(input);
}
file1.close();
ofstream file2;
file2.open("output.txt");
file2 << m3.getMax();
file2.close();
return 0;
}
The code is slightly more complex, but the program size is only 35 KB, with little dynamic allocation.
After replacing the 'for' loops with a sort of vector 1 'V1' (in descending order), the program compares the products 'V1[0] * V1[1] * V1[2]' and 'V1[0] * V1[N] * V1[N - 1', and then prints the maximum in file output.txt:
#include <vector>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
int N;
long long max = -9223372036854775807;
int input;
vector<long long> V1;
ifstream file1;
file1.open("input.txt");
file1 >> N;
V1.resize(N);
for (int i = 0; i < N; i++){
file1 >> V1[i];
}
sort(V1.begin(), V1.end(), greater<int>());
N -= 1;
max = V1[0] * V1[1] * V1[2];
if (max < V1[0] * V1[N] * V1[N - 1])
max = V1[0] * V1[N] * V1[N - 1];
ofstream file2;
file2.open("output.txt");
file2 << max;
file2.close();
}

Strange output with large vectors

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).