Memory Limit Exceeded while reading integers into the vector - c++

I am trying to read integer values from text file into a vector.
Input file ip1.txt has the following content:
4
-1000 -2000 -3000 -4000
int maxsub(vector<int> a, int size)
{
a.erase(a.begin());
vector<int> sum;
for(vector<int>::iterator w=a.begin(); w <= a.begin()+size-1; ++w)
{
int j;
int s=*w;
for(int t=0; t <= size-1; t++)
{
j = s + a[t];
sum.push_back(j);
}
a.pop_back();
}
std::sort(sum.begin(),sum.end());
int u = sum.size()-1;
int m = sum.at(u);
return m;
}
int main()
{
std::vector<int> nums( (std::istream_iterator<int>(std::cin)),
std::istream_iterator<int>() );
int k = nums[0];
int u = maxsub(nums,k);
cout << u <<endl;
}
I am getting Warning message as 'Memory Limit Exceeded'
How can i resrict vector to read only till -4000 in the input file,I am using file redirection
*./123 < ip1.txt *

Bug at the source code.
All loops in maxsub()
for(vector<int>::iterator w=a.begin(); w <= a.begin()+size-1; ++w)
for(int t=0; t <= size-1; t++)
has iterations from 0 to size-1 elements (=size all in all elements), but after code
a.erase(a.begin());
vector 'a' has only (size-1) elements.
Therefore, all for-operators is 'outside-the-boundary'.
I think, it's cause of warning message.

If you know that the first number will be the length of your vector, why not take advantage of it?:
int length = 0;
std::cin >> length;
std::vector<int> numbers;
numbers.reserve(length);
then you can just use simple for loop that checks whether the number has been successfully extracted from the stream and also prevents more than specific amount of numbers being read:
int number;
for (int i = 0; (i < length) && (std::cin >> number); ++i)
{
numbers.push_back(number);
}
Don't forget to #include <iostream>, #include <sstream> and #include <vector>. Also note that std::cin can be easily replaced with file stream :)

Write a for loop
std::vector<int> nums;
int size;
std::cin >> size;
for (int i = 0; i < size; ++i)
{
int val;
std::cin >> val;
nums.push_back(val);
}

'a.begin()+size-1' is before begin():
Having
for(vector<int>::iterator w=a.begin(); w <= a.begin()+size-1; ++w)
and
int k = nums[0];
int u = maxsub(nums,k);
and
nums[0] = -1000;
size is -1000
If you want to exclude the first and last element:
if( ! a.empty()) {
// Not erasing the first element: a.erase(a.begin());
for(vector<int>::size_type i = 1; i < a.size() - 1; ++i);
}

Related

Finding max value in a array

I'm doing a program that finds the max value in a array. I done it but I found a strange bug.
#include<iostream>
using namespace std;
int main() {
int n; //input number of elements in
cin >> n;
int arr[n];
for (int i = 0; i < n; i++) {
cin >> arr[i]; //input array's elements
} int max_value = arr[0];
for (int i = 1; i <= n; i++) {
if (arr[i] > max_value) {
max_value = arr[i];
}
} cout << max_value;
return 0;
}
When I put 5 as first line for the number of elements and 2, 7, 6, 8, 9 as the elements of the array. It returns 16 instead of 9. Please help
In Arrays the first index starts with 0 and ends in n - 1 assuming the array is of length n
so when looping from i = 1 to i <= n. n is now larger than n - 1.
the solution would be to start from 0 and end at i < n hence:
#include<iostream>
using namespace std;
int main() {
int n; //input number of elements in
cin >> n;
int arr[n];
for (int i = 0; i < n; i++) {
cin >> arr[i]; //input array's elements
} int max_value = arr[0];
for (int i = 0; i < n; i++) {
if (arr[i] > max_value) {
max_value = arr[i];
}
}
cout << max_value;
return 0;
}
you could also use the std::max function like so:
for(int i = 0; i < n; i ++) {
max_value = max(max_value, arr[i]);
}
The other posts already pointed out problem in your code.
You should be aware of that int arr[n]; is not permitted in standard C++.
[GCC and CLANG compiler support it in C++ as an extension]
An alternative is to allocate memory dynamically:
int *arr = new int[n];
and to find maximum value you can use std::max_element:
int max_value = *(std::max_element(arr, arr + n));
Instead of dynamic array, its better to use vector STL (make yourself familiar with Containers Library). You can do:
std::vector <int> arr;
for (int i = 0; i < n; i++) {
int input;
std::cin >> input;
arr.push_back(input);
}
int max_value = *std::max_element(arr.begin(), arr.end());
std::cout << "Max element is :" << max_value << std::endl;
in your second for do this
for (int i = 1; i < n; i++) {
if (arr[i] > max_value) {
max_value = arr[i];
}
delete '=' from i <= n because i is index which start from 0
and instead of this
int arr[n];
do this
int *arr = new int[n];

Why the output is not showing?

My program is to find the smallest positive number missing from an array. With the following input I expect an output of 2.
6
0
-9
1
3
-4
5
My problem is that it does not give any output. Can anyone explain this please?
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
int array[n];
for (int i = 0; i < n; i++)
{
cin >> array[n];
}
int const N = 1e4+2;
bool indexarray[N];
for (int i = 0; i < N; i++)
{
indexarray[i] = false;
}
for (int i = 0; i < n; i++)
{
if (array[i] > 0)
{
indexarray[array[i]] = true;
}
}
int ans = -1;
for (int i = 1; i < N; i++)
{
if (indexarray[i] == false)
{
ans = i;
}
}
cout << ans << endl;
return 0;
}
I think because int array[n]; makes an array called array with n elements in it, with the first one starting at array[0].
cin >> array[n]; needs to modify array[n], but because the first element is array[0], the last element is array[n-1], and array[n] does not exist. Your code gave an error and exited.
Try changing
for (int i = 0; i < n; i++)
{
cin >> array[n];
}
to
for (int i = 0; i < n; i++)
{
cin >> array[i];
}
Also, I think variable length arrays are non-standard, so maybe try changing that. Replace it with std::vector<int> array(n) should work.

Displaying first element user input in an Array

We can define the term 'value of a name' as the average position of
the letters in the name, calculating 'A' as 1, 'B' as 2, 'C' as 3, and
so on. The value of "BOB" would be (2 + 15 + 2)/ 3 = 6. According to
this value, the names will be arranged from the smallest towards the
biggest in the output. When two or more names have the same value,
the name which is in the first position in the original list (the
first one the user inputs) should show up first in the sorted list
(the output).
Input In the first line we have an integer N (1 <= N <= 100), which is
the number of names. In every of the N lines we have one name ([A-Z],
no empty spaces). Names contain 1 - 200 letters.
Output Print out the sorted list (one name in a line).
Test-case
Input: 3 BOB AAAAAAA TOM Output: AAAAAAA BOB TOM
I tried something, and the code seemed to work, I just had a problem with the output. I couldn't find a way to arrange the names with the same value, according to their position in the original list. Here's the other test-case I tried, but didn't figure out:
Input:
10
COSOPYILSPKNKZSTUZVMEERQDL
RRPPNG
PQUPOGTJETGXDQDEMGPNMJEBI
TQJZMOLQ
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
YNWEPZKNBOOXNZVWKIUS
LV
CJDFYDMYZVOEW
TMHEJLIDEHT
KGTGFIFWYTKPWTYQQPGKRRYFXN
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
My output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
CJDFYDMYZVOEW // these two
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM // should be arranged with their places switched
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
#include <iostream>
#include <string>
using namespace std;
int main() {
int N;
cin >> N;
string words[N];
int res[N];
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> words[i];
word = words[i];
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res[i] = value;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
for (int i = 0; i < N; i++) {
cout << words[i] << endl;
}
return 0;
}
string words[N];
int res[N];
This here is not valid C++, you can not size a stack array using a runtime variable, although some compilers might support such a feature. You might use say std::vector instead, which behaves much like an array.
vector<string> words;
vector<int> res;
for (int i = 0; i < N; i++) {
int sum = 0;
int value = 0;
int temp = 0;
string word;
cin >> word;
words.push_back(word);
for (int j = 0; j < word.length(); j++) {
sum += (int)word[j] - 64;
}
value = sum / word.length();
res.push_back(value);
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
The ordering is because your sorting algorithm is not stable. Stable means that items with equal values will maintain the same order relative to each other.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (res[i] < res[j]) {
swap(res[i], res[j]);
swap(words[i], words[j]);
}
}
}
What you have is very close to bubble sort, which is stable.
for (int i = 0; i < N; i++) {
for (int j = 0; j < N - i - 1; j++) { // i elements sorted so far
if (res[j] > res[j + 1]) {
swap(res[j], res[j + 1]);
swap(words[j], words[j + 1]);
}
}
}
C++ also provides a stable sort in <algorithm>, but it can't function directly on two arrays like this unfortunately, one option is to compute the value on the fly, another could be to make a class holding both items and sort that, or another to sort the indices.
std::stable_sort(words.begin(), words.end(), [&](auto &a, auto &b)
{
int suma = 0, sumb = 0; // better yet, make a "int value(const string &str)" function.
for (int j = 0; j < a.length(); j++) {
suma += (int)a[j] - 64;
}
for (int j = 0; j < b.length(); j++) {
sumb += (int)b[j] - 64;
}
int valuea = suma / a.length();
int valueb = sumb / b.length();
return valuea < valueb;
});
A class containing both items is pretty straight forward, for indices, make a 3rd array and sort that.
vector<size_t> indices;
...
string word;
cin >> word;
indices.push_back(words.size());
words.push_back(word);
...
std::stable_sort(indices.begin(), indices.end(), [&](auto a, auto b){ return res[a] < res[n]; });
for (int i = 0; i < N; i++) {
cout << words[indices[i]] << endl;
}
A possible solution could be order the result array during construction.
When you add the words in the result array, use the result obtained to add the word in the right place. In this way you can check if exist already the same value and add the new word after the previous with the same value.
After reading the next word use insertion sort (wiki) which is stable
read word
calculate value
insert in a right place in the array
go to 1 until i < N otherwise print out
Doesn't require additional sorting procedure.
in python:
def sort_list(list1, list2):
zipped_pairs = zip(list2, list1)
z = [x for _, x in sorted(zipped_pairs)]
return z
times = int(input())
entries = []
ordered = []
for x in range(times):
entries.append(input())
for x in entries:
chars = []
for y in x:
chars.append(ord(y) - 96)
ordered.append(sum(chars))
print(sort_list(entries,ordered))
If you use a std::multimap<int, std::string>, there would be no need to sort, as the key would already serve as the sorting criteria.
Here is a solution using std::multimap:
#include <string>
#include <numeric>
#include <iostream>
#include <sstream>
#include <map>
// Test data
std::string test = "10\n"
"COSOPYILSPKNKZSTUZVMEERQDL\n"
"RRPPNG\n"
"PQUPOGTJETGXDQDEMGPNMJEBI\n"
"TQJZMOLQ\n"
"BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM\n"
"YNWEPZKNBOOXNZVWKIUS\n"
"LV\n"
"CJDFYDMYZVOEW\n"
"TMHEJLIDEHT\n"
"KGTGFIFWYTKPWTYQQPGKRRYFXN\n";
int main()
{
std::istringstream strm(test);
// Read in the data
std::multimap<int, std::string> strmap;
int N;
strm >> N;
std::string word;
for (int i = 0; i < N; ++i)
{
strm >> word;
// get the average using std::accumulate and divide by the length of the word
int avg = std::accumulate(word.begin(), word.end(), 0,
[&](int total, char val) { return total + val - 'A' + 1; }) / word.length();
// insert this value in the map
strmap.insert({ avg, word });
}
// output results
for (auto& w : strmap)
std::cout << w.second << "\n";
}
Output:
TMHEJLIDEHT
PQUPOGTJETGXDQDEMGPNMJEBI
BKNGFEJZWMJNJLSTUBHCFHXWMYUPZM
CJDFYDMYZVOEW
RRPPNG
COSOPYILSPKNKZSTUZVMEERQDL
KGTGFIFWYTKPWTYQQPGKRRYFXN
TQJZMOLQ
YNWEPZKNBOOXNZVWKIUS
LV
The std::accumulate is used to add up the values to get the average.
Or just order them in the end (You won't need the 2nd array):
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int sumA = 0, sumB = 0;
for (int k = 0; k < words[i].size(); k++)
sumA += words[i][k] - 'A' + 1;
for (int k = 0; k < words[j].size(); k++)
sumB += words[j][k] - 'A' + 1;
if (sumA / words[i].size() > sumB / words[j].size())
swap(words[i], words[j]);
}
}
As they shown above, it's way better to use a vector to store your data.

removing double elements in an array

I am trying to remove double elements in an array. I developed a simple code, but it is still not working. Is it possible to hint for some input maybe I haven't tried. I tried corner and test cases. The following is the problem statement:
A sequence of numbers given. Remove element’s doubles, leaving first copy.
Input: Contains a natural n (n ≤ 100000) – the n quantity numbers in a sequence, then n non-negative numbers – elements of the sequence which module is not greater than 999.
output: changed sequence.
It seems I can't get what might be the problem
#include <iostream>
//#include <cmath>
//#include <climits>
#define SIZE 100000
using namespace std;
int main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int n, k, p;
bool tag; tag = false;
cin >> n;
long long int *a = new long long int[n];
long long int b[SIZE];
for (int i = 0; i < n; i++) { cin >> a[i]; }
for (int i = 0; i < n; i++) { k = 0;
for (int j = i + 1; j < n; j++) {
if (a[i] == a[j]) { b[k] = j-k; k++; tag = true; }
}
if (tag) {
for (int i = 0; i < k; i++) {
p = b[i];
for (int i = p; i < n; i++) { a[i] = a[i + 1]; }
n--;
}
tag = false;
}
}
for (int i = 0; i < n; i++) { cout << a[i] << " "; }
return 0;
}
Input: 6 1 2 2 4 3 4 Output: 1 2 4 3
You can use unordered_set and vector
int n; cin >> n;
long long int x;
unordered_set<long long int>myset;
vector<long long int>v1;
for (int i = 0; i < n; i++)
{
cin>>x;
if(myset.find(x)==myset.end())
{
myset.insert(x);
v1.push_back(x);
}
}
for(int i=0;i<v1.size();i++)
{
cout<<v1[i]<<" ";
}
You could use in you advantage the fact that input values are in the range from 0 to 999.
A simple bool used[1000]{} could be used to flag if the current value has been used already before pushing it to cout, thus ensuring both O(n) complexity and limited memory usage (1000 bytes for the bool[]}.
Here's a sample solution around this idea:
#include<iostream>
#define MAX_VALUE 999
using namespace std;
int main() {
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
bool used[MAX_VALUE + 1]{};
size_t n;
cin >> n;
for (size_t num, i = 0; i < n; ++i) {
cin >> num;
if (!used[num]) {
cout << num << " ";
used[num] = true;
}
}
return 0;
}
You could try creating a second array of unique numbers as you go. I will demonstrate with a vector for the sake of simplicity.
std::vector<int> v;
for (int i = 0; i < n; i++) {
if (std::find(v.begin(), v.end(), arr[i]) == v.end()) {
v.push_back(arr[i]);
}
}
Then, you just write the contents of the vector to the output file.
Here is my version of O(n) complexity. Your solution may exceed time-limit ( if it is low )
bool check[2000];
for (int i = 0; i < 2000; i++) check[i] = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
// +999 to avoid negative numbers
check[a[i] + 999] = 1;
}
bool isPrint = false;
for (int i = 0; i < n; i++) {
if (check[a[i] + 999]) {
// mark false if already printed
check[a[i] + 999] = 0;
if (isPrint) printf(" ");
printf("%d", a[i]);
isPrint = true;
}
}

How can I properly add and access items to a multidimensional vector using loops?

I have this program that is trying to determine how many unique items are within some intersecting sets. The amount of input entirely depends on the the first value n, and then the amount of sets entered afterward. For example, if I start with entering n = 2, I am expected to enter 2 integers. The program then determines how many intersections there are between n items (this is like choosing 2 items from n items). This goes on as k increments. But that's kind of beyond the point. Just some background info.
My program adapts correctly and accepts the proper amount of input, but it stops working properly before the first for loop that is outside of the while loop. What I have tried to do is make a vector of integer vectors and then add every other row (when index starts at 0 AND index starts at 1). But I am guessing I have constructed my vectors incorrectly. Does anybody see an error in my vector logic?
#include <iostream>
#include <vector>
using namespace std;
int fact (int m) {
if (m <= 1)
return 1;
return m * fact(m - 1);
}
int comb (int n, int k) {
return fact(n)/(fact(n-k)*fact(k));
}
int main() {
int n = 0;
int k = 2;
int sum = 0;
int diff = 0;
int final = 0;
vector <vector <int> > arr;
cin >> n;
while (n > 0) {
vector <int> row;
int u;
for (int i = 0; i < n ; ++i) {
cin >> u;
row.push_back(u);
}
arr.push_back(row);
n = comb(row.size(), k);
k++;
}
for (int i = 0; i < arr.size(); i+2)
for (int j = 0; j < arr[i].size(); ++j)
sum += arr[i][j];
for (int i = 1; i < arr.size(); i+2)
for (int j = 0; j < arr[i].size(); ++j)
diff += arr[i][j];
final = sum - diff;
cout << final;
return 0;
}
for (int i = 0; i < arr.size(); i+=2)
^
You want to do i+=2 or i=i+2, else the value of i is never changed, leading to an infinite loop.