I'm learning C++ and when practicing on Hackerrank, I encountered vectors containing vectors for the first time. This is the problem to solve.
From the program provided below, I want to know:
Is it the correct way to declare the required vector as I did?
Does the statement "a.resize(i)" at line 27 work as I intend it to?
#include<iostream>
#include<vector>
#include<array>
bool inrange(int min, int max, int x)
{
//check if x is in range
return (x >= min && x <= max);
}
int main(void)
{
int q{}, n{}; //for no. of queries & no. of elements in array
std::cin >> q >> n;
if (inrange(1, 100000, q)) //ensure q to be in specified range
{
if (inrange(1, 100000, n))
{
//for declaring vector of vectors
using innertype = std::vector<int>;
std::vector <innertype> a;
//array to store no. of elements in each ith array
std::vector <int> ki;
for (int i{ 0 }; i < n; ++i)
{
//extend vector by one element
>line 27 a.resize(i);
//get the array for ith position
int j{ 0 }; char buffer;
do
{
//extend vector at ith index by one element
a[i].resize(j);
std::cin >> a[i][j];
std::cin >> buffer;
++j;
} while (buffer != '\n');
ki.resize(j);
ki[i] = j;
}
//take indexes for query1 and query2 to print requested elements
int i{}, j{};
std::cin >> i >> j;
std::array q1request{ i,j };
std::cin >> i >> j;
std::array q2request{ i,j };
//print elements "a[i][j]"
std::cout << a[q1request[i]][q1request[j]] << '\n';
std::cout << a[q1request[i]][q2request[j]];
}
}
return 0;
}
The program terminates after taking two inputs.
Debug Assertion Failed!
Expression: vector subscript out of range
There is nothing really wrong with your usage of vector apart from indexing (maybe a bit strange, but not wrong). The usage of the resize method of the vector is missused. For the pre-allocation of the vector, two methods are used in general. resize() and reserve().
One can be used in case you need indexing the vector.
std::vector<int> test(10, 0); // creating vector of 10 items set to 0
test.resize(100); // resizing to allocate space for 100 elements
// test.size() == 100
for(size_t i = 0; i < test.size(); ++i)
{
test[i] = i;
std::cout << "Filling " << i << "th element." << std::endl;
}
The other is used usually when you dont need the index.
std::vector<int> test;
test.reserve(100); // reserve space for at least 100 elements
// test.size() == 0
for(size_t i = 0; i < 100; ++i)
{
test.push_back(i); // will not allocate new memory
}
The issue you have is that you resize the vector to hold 0 elements in 1st iteration and then you access element at index 0. The same would go for any other subsequent index.
Related
I am new to c++ language. I am trying to solve a problem using function. I have to print the pentagon numbers untill the integer input, but when function returns the values, it only prints one value. I would love some help with it.
#include<iostream>
using namespace std;
int pent(int num){
int p;
for(int i=1;i<=num;i++){
p=(i*(3*i-1)/2);
}
return p;
}
int main(){
int num;
cin>>num;
int sender=pent(num);
cout<<sender<<endl;
return 0;
}
Your function returns int, that is a single integer. To return more, you can use std::vector. As you probably are not familiar with it, I will give you some pointers...
The most simple constructor creates a vector with no entries:
std::vector<int> x;
You can reserve space for elements via reserve:
x.reserve(num);
The vector still has no elements, but it already allocated enough space to hold num elements. This is important, because when we will add elements the vector will grow and that potentially requires to copy all elements to a different place in memory. We can avoid such frequent reallocations by reserving enough space upfront.
To add elements to the vector you can use push_back:
x.push_back(42);
Eventually to print all elements of the vector we can use a range-based for loop:
for (auto element : x) std::cout << element << " ";
So you can rewrite your code like this:
#include <iostream>
#include <vector>
std::vector<int> pent(int num){
std::vector<int> result;
result.reserve(num);
for(int i=1;i<=num;i++){
result.push_back(i*(3*i-1)/2);
}
return result;
}
int main(){
int num;
std::cin >> num;
auto sender = pent(num);
for (auto number : sender) std::cout << number << " ";
}
In your program, from your pent() function you are only returning last calculated value. In you ever time, you are overwriting you variable p.
So there is a way which #asmmo is suggesting, to print in pent() function.
Or you can pass a vector to your pent() function and store values in that and print it in main function.
For your ref:
void pent(int num, vector<int> &arr) {
int p;
for (int i = 1; i <= num; i++) {
arr[i-1] = (i*(3 * i - 1) / 2);
}
}
int main() {
int num;
cin >> num;
vector<int> arr(num);
pent(num, arr);
for (int i = 0; i < num; i++) {
cout << arr[i] << endl;
}
return 0;
}
I am trying to remove the duplicate elements in a sorted vector such that each element appears only once.
My code:
#include <iostream>
#include <vector>
using namespace std;
void removeDuplicates(vector<int> &nums)
{
vector<int>::iterator it;
unsigned int j = 1;
while(j < nums.size()-1)
{
if(nums.at(j) == nums.at(j-1))
{
it = nums.begin()+j;
nums.erase(it);
--j; // for every removal, correct the index
}
j += 1; // increment the index
}
}
int main ()
{
vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++)
{
cout << vect[i] << " ";
}
cout << endl;
return 0;
}
When I run the code, the output is
The vector unique elements are: 0 1 2 3 4
The question gives the following instruction:
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
In my code, the Big O time complexity is O(n).
How can I remove the duplicates in-place with an extra memory of O(1)?
How can remove the duplicates in-place with a time complexity of O(1)?
You can't. Even with the vector sorted, you simply must compare every single element to know whether it is unique or not. O(N) is optimal.
However, O(1) time complexity wasn't required by the task either:
... with O(1) extra memory.
There was no mention of time complexity constraint - only space complexity.
The simplest way to get rid of duplicates is to use what's already available in the standard library:
nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
You can implement it in place (no extra memory) with a complexity O(n) by simply using two indices, one for reading the elements and one for writing.
#include <iostream>
#include <vector>
void removeDuplicates(std::vector<int> &nums)
{
unsigned int j = 1;
for (unsigned int i = 1; i < nums.size(); i++)
{
if(nums.at(i) != nums.at(i-1))
{
nums.at(j++) = nums.at(i);
}
}
nums.resize(j);
}
int main ()
{
std::vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
std::cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++) {
std::cout << vect[i] << " ";
}
std::cout << "\n";
return 0;
}
I was told on here to use vectors instead of arrays for this particular solution ( My original solution using to dynamically allocate arrays) my problem is I don't really understand vectors, my book only covers a small section. So, maybe I am doing something wrong? I'm just trying to learn a different way in solving it with vectors. So, when I ask is it possible to dynamically allocate a vector. What I mean is it legal to do this std::vector<int*> vect= nullptr;, if not why? Also it would be really helpful to see an example how to modify my original solution with vectors. I'm a beginner just trying to learn from my mistakes.
#include <iostream>
#include <vector>
void sortAscendingOrder(int*, int );
void LowestTestScore(int*, int);
void calculatesAverage(int*,int);
int main()
{
std::vector<int*> vect= nullptr;
int input;
std::cout << "Enter the number of testscores you want to enter." <<std::endl;
std::cin >> input;
vect = new int[input];
for(int count =0; count < input; count++)
{
std::cout << "Enter the test score" << (count +1) <<":" <<std::endl;
std::cin >> vect[count] ;
while( vect[count] < 0)
{
std::cout <<"You enter a negative number. Please enter a postive number." <<std::endl;
std::cin >> vect[count];
}
}
sortAscendingOrder(vect,input);
for(int count =0; count < input;count++)
{
std::cout << "\n" <<vect[count];
std::cout << std::endl;
}
LowestTestScore(vect,input);
calculatesAverage(vect,input);
return 0;
}
void sortAscendingOrder(int* input,int size)
{
int startScan,minIndex,minValue;
for(startScan =0; startScan < (size-1);startScan++)
{
minIndex = startScan;
minValue = input[startScan];
for(int index = startScan+1;index<size;index++)
{
if(input[index] < minValue)
{
minValue = input[index];
minIndex = index;
}
}
input[minIndex]=input[startScan];
input[startScan]=minValue;
}
}
void LowestTestScore(int* input, int size)
{
int count =0;
int* lowest = nullptr;
lowest = input;
for(count =1; count <size;count++)
{
if(input[count] < lowest[0])
{
lowest[0] = input[count];
}
}
std::cout << "Lowest score" << *lowest;
}
void calculatesAverage(int* input, int size)
{
int total = 0;
int average =0;
for(int count = 0; count < size; count++)
{
total += input[count];
}
average =(total/size-1);
std::cout << "Your average is" << average;
}
Dynamic allocation of an array is required when you want to increase the size of an array at run-time. Just like arrays, vectors used contiguous storage locations for their elements. But, unlike arrays, their size can change dynamically, with their storage being handled automatically by the container.
Vectors do not reallocate each time an element is added to the container. It pre-allocates some extra storage to accommodate future growth. Libraries can implement different strategies for growth to balance between memory usage and reallocation, but in any case, reallocation should only happen at logarithmically growing intervals of size so that the insertion of individual elements at the end of the vector can be provided with amortized constant time complexity (see push_back)
To answer your question:
Yes, it is possible to dynamically allocate a vector and no, it requires no extra effort as std:vector already does that. To dynamically allocate vectors is therefore, a redundant effort.
You can write:
#include<vector>
typedef std::vector< std::vector<double> >vec_array;
vec_array name(size_x, std::vector<double>(size_y));
This means: size instances of a std::vector<double>, each containing size_y doubles (initialized to 0.0).
Or, you can simply use vector to increase the container size (knowing it handles storage requirements by itself) like:
#include <vector>
vector<int> vec_array;
int i;
for(i=0;i<10;i++)
vec_array.push_back(i);
I'm creating this very simple C++ program.
the program asks the user to enter a few integers and stores them in an array.but when a specific integer(for example 50)is entered,the input is ended and then,all of the integers are displayed on the screen except for 50.
for example:
input:
1
2
88
50
output:
1
2
88
the error i'm getting is when i use cout to print the array,all of numbers are shown,including 50 and numbers i did'nt even entered.
this is my code so far:
#include<iostream>
int main() {
int num[100];
for(int i=0;i<=100;i++) {
cin >> num[i];
if (num[i]!=50) break;
}
for(int j=0;j<=100;j++) {
cout << num[j] << endl;
}
return 0;
}
Change the program the following way
#include<iostream>
int main()
{
const size_t N = 100;
int num[N];
size_t n = 0;
int value;
while ( n < N && std::cin >> value && value != 50 ) num[n++] = value;
for ( size_t i = 0; i < n; i++ ) std::cout << num[i] << std::endl;
return 0;
}
Here in the first loop variable n is used to count the actual number of entered values. And then this variable is used as the upper bound for the second loop.
As for your program then the valid range of indices for the first loop is 0-99 and you have to output only whose elements of the array that were inputed.
A do while loop is more suitable for your problem. The stop condition will check if the number fit inside the array (if k is not bigger than 100) and if number entered is 50.
#include<iostream>
using namespace std;
int main() {
int num[100];
int k = 0;
// A do while loop will be more suitable
do{
cin >> num[k++];
}while(k<100&&num[k-1]!=50);
for (int j = 0; j < k-1; j++) {
cout << num[j] << endl;
}
return 0;
}
Also, a better solution to get rid of 100 limitation is to use std::vector data structure that automatically adjust it's size, like this:
vector<int> num;
int temp;
do {
cin >> temp;
num.push_back(temp);
} while (temp != 50);
Note, you can use temp.size() to get the number of items stored.
You read up to 101 numbers, but if you enter 50 you break the loop and go for printing it. In the printing loop you go through all 101 numbers, but you actually may have not set all of them.
In the first loop count in a count variable the numbers you read until you meet 50 and in the printing loop just iterate count-1 times.
You have allocated an array of 100 integers on the stack. The values are not initialized to zero by default, so you end up having whatever was on the stack previously appear in your array.
You have also off-by-one in both of your loops, you allocated array of 100 integers so that means index range of 0-99.
As the question is tagged as C++, I would suggest that you leave the C-style array and instead use a std::vector to store the values. This makes it more flexible as you don't have to specify a fixed size (or manage memory) and you don't end up with uninitialized values.
Little example code (requires C++11 compiler):
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers; // Store the numbers here
for(int i = 0; i < 100; ++i) // Ask a number 100 times
{
int n;
std::cin >> n;
if( n == 50 ) // Stop if user enters 50
break;
numbers.push_back(n); // Add the number to the numbers vector
}
for (auto n : numbers) // Print all the values in the numbers vector
std::cout << n << std::endl;
return 0;
}
There are just 2 changes in your code check it out :
int main()
{
int num[100],i; //initialize i outside scope to count number of inputs
for(i=0;i<100;i++) {
cin >> num[i];
if (num[i]==50) break; //break if the entered number is 50
}
for(int j=0;j<=i-1;j++)
{
cout << num[j] << endl;
}
return 0;
}
Okay, others already pointed out the two mistakes. You should use i < 100 in the loop conditions instead of i <= 100 and you have to keep track of how many elements you entered.
Now let me add an answer how I think it would be better.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; // a temp variable in the for loop.
numbers.size() < 100 && // check that we have less than 100 elements.
std::cin >> temp && // read in the temp variable,
// and check if the read was a success.
temp != 50) // lastly check that the value we read isn't 50.
{
numbers.push_back(temp); // Now we just add it to the vector.
}
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i]; // Now we just print all the elements of
// the vector. We only added correct items.
}
The above code doesn't even read anymore numbers after it found 50. And if you want to be able to enter any number of elements you just have to remove the check that we have less than 100 elements.
Now I commented the above code a bit much, if you compress it it'll reduce to just:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int i = 0; i < numbers.size(); ++i)
std::cout << numbers[i];
}
If you can use the C++11 standard it reduces to:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers; // Create an empty vector.
for (int temp; numbers.size() < 100 && std::cin >> temp && temp != 50)
numbers.push_back(temp);
for (int element : numbers)
std::cout << element;
}
for (auto element : numbers) is new, it basically means for every int 'element' in 'numbers'.
Is there such a thing as a jagged array in C or C++?
When I compile this:
int jagged[][] = { {0,1}, {1,2,3} };
I get this error:
error: declaration of `jagged' as multidimensional array must have bounds for all dimensions except the first
In C I would use an array of pointers.
For instance:
int *jagged[5];
jagged[0] = malloc(sizeof(int) * 10);
jagged[1] = malloc(sizeof(int) * 3);
etc etc.
There's a bunch of ways to do it. Here's another way:
int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int *jagged[] = { jagged_row0, jagged_row1 };
If you just want to initialise it, you can say:
int jagged[][3] = { {0,1}, {1,2,3} };
but the array will still have the shape [2][3]. If you want a true jagged array, you will have to create it dynamically. And if you do that, and are using C++, you should use a std::vector, as friol suggests.
In C++ (not compiled, and probably there's a more compact syntax):
std::vector<std::vector<int> > myArray;
myArray.push_back(std::vector<int>());
myArray.push_back(std::vector<int>());
myArray[0].push_back(0);
myArray[0].push_back(1);
myArray[1].push_back(1);
myArray[1].push_back(2);
myArray[1].push_back(3);
So now you can access the elements with, for example, myArray[0][0], etc.
In C99 you can do the following:
int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int (*jagged[])[] = { &jagged_row0, &jagged_row1 }; // note the ampersand
// also since compound literals are lvalues ...
int (*jagged2[])[] = { &(int[]){0,1}, &(int[]){1,2,3} };
The only difference here (as compared to rampion's answer) is that the arrays don't decay to pointers and one has to access the individual arrays via another level of indirection - (e.g. *jagged[0] - and the size of each row has to be recorded - i.e. sizeof(*jagged[0]) will not compile) - but they're jagged-appearing to the bone ;)
The reason you got the error is that you must specify the bounds for at least the outer dimension; i.e.
int jagged[][3] = {{0,1},{1,2,3}};
You cannot have jagged[0] be a 2-element array of int and jagged[1] be a 3-element array of int; an N-element array is a different type from an M-element array (where N != M), and all elements of an array must be the same type.
What you can do is what the others have suggested above and create jagged as an array of pointers to int; that way each element can point to integer arrays of different sizes:
int row0[] = {0,1};
int row1[] = {1,2,3};
int *jagged[] = {row0, row1};
Even though row0 and row1 are different types (2-element vs. 3-element arrays of int), in the context of the initializer they are both implicitly converted to the same type (int *).
With C++11 initializer lists this can be written more compactly:
#include <vector>
#include <iostream>
int main() {
// declare and initialize array
std::vector<std::vector<int>> arr = {{1,2,3}, {4,5}};
// print content of array
for (auto row : arr) {
for (auto col : row)
std::cout << col << " ";
std::cout << "\n";
}
}
The output is:
$ g++ test.cc -std=c++11 && ./a.out
1 2 3
4 5
For reference:
http://en.cppreference.com/w/cpp/utility/initializer_list
You can also use the compound literals in c to initialize a truly jagged array which is contiguous in memory as follows:
int (*arr[]) = { (int []) {0, 1}, (int []){ 2, 3, 4}, (int []){5, 6, 7, 8} }
This will be laid out contiguously in memory.
By using dynamic allocation in cpp we can create jagged arrays.
For example:
#include<iostream>
using namespace std;
int main(){
int n;
cout<<"Enter n:";
cin>>n;
cout<<"Enter elements:";
int **p = new int *[n];
for(int i=0;i<n;i++){
p[i] = new int[i+1];
for(int j=0;j<(i+1);j++){
cin>>p[i][j];
}
}
cout<<"Jagged Array:"<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<(i+1);j++){
cout<<p[i][j]<<" ";
}
cout<<endl;
}
for(int i=0;i<n;i++){
delete []p[i];
}
delete []p;
}
For n=3, we have created a jagged array in the following look:
Enter n: 3
Enter elements:
1
1 2
1 2 3
Jagged Array:
1
1 2
1 2 3
//
//jaggedArrays.cpp
//
//program to implement jagged arrays in c++
//
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int rows, i, j;
cout << endl << "Enter no of rows : ";
cin >> rows;
int columnsSizeOfEachRow[rows];
cout << endl;
for( i = 0 ; i < rows ; i++ )
{
cout << "Enter column size for row no " << i + 1 << " : ";
cin >> columnsSizeOfEachRow[i];
}
int *jaggedArray[rows];
for (i = 0 ; i < rows ; i++)
jaggedArray[i] = new int[columnsSizeOfEachRow[i]];
cout << endl;
for(i = 0 ; i < rows ; i++)
{
for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
{
cout << "Array[" << i + 1 << "][" << j + 1 << "] << ";
cin >> jaggedArray[i][j];
}
cout << endl;
}
cout << endl << endl << "Jagged array is as follows : " << endl;
for( i = 0 ; i < rows ; i++)
{
for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
cout << setw(3) <<jaggedArray[i][j] << " ";
cout << endl;
}
return 0;
}
The jagged arrays do exist in c++/c but the syntax is quite complex and you have to handle many things.
There are two types of jagged arrays in c++.
1) STATIC JAGGED ARRAY(A 2d array in which the size will be a constant number and there will be different number of columns in each row).
2) DYNAMIC JAGGED ARRAY(A 2d array in which the size will be any number taken from user and there will be different number of columns in each row)
1)STEPS OF IMPLEMENTING STATIC JAGGED ARRAY
Using array and a pointer
1) Declare 1-D arrays with the number of rows you will need
2) The size of each array(array for the elements in the row) will be the number of columns (or elements) in the row
3) Declare a 1-D array of pointers that will hold the addresses of the arrows
4) The size of the 1-D array is the number of rows you want in the jagged array
#include<iostream>
#include<string>
using namespace std;
int main()
{
int row0[4] = { 1,2,3,4 };
int row1[2] = { 5,6 };
int* jagged[2] = { row0,row1 };
int Size[2] = { 4,2 }, k = 0;
for (int i = 0; i < 2; i++)
{
int* ptr = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
cout << *ptr << "";
ptr++;
}
cout << endl;
k++;
jagged[i]++;
}
return 0;
}
The output is as follows
123456
1)STEPS OF IMPLEMENTING DYNAMIC JAGGED ARRAY
Using an array of pointer
1) Declare an array of pointers(jagged array)
2) The size of this array will be the number of rows required in the jagged array
3) For each pointer in the array allocate memory for the number of elements you want in this row.
#include<iostream>
#include<string>
using namespace std;
int main()
{
//2 rows
int* jagged[2];
//Allocate memeory for the elements in the row 0
jagged[0] = new int[1];
//Allocate memory for the elements in row 1
jagged[1] = new int[5];
//Array to hold the size of each row
int Size[2] = { 1,5 },k = 0, number = 100;
//User enters the numbers
for (int i = 0; i < 2; i++)
{
int* p = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
*p = number++;
//move the pointer
p++;
}
k++;
}
k = 0;
//Display elements in Jagged array
for (int i = 0; i < 2; i++)
{
int* q = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
cout << *q << "";
//move the pointer to the next element
q++;
}
cout << endl;
k++;
//move the pointer to the next row
jagged[i]++;
}
delete[] jagged[0];
delete[] jagged[1];
return 0;
}
The output is as follows
100
101102103104105
No, there are no jagged multidimensional arrays in C nor C++. You can create various constructs that perform similar function at some memory cost (like array of pointers to arrays), but not an actual C-style multidimensional array.
The reason is that C-style arrays, no matter how many dimensions, occupy contiguous memory area with no metadata. So, memory-wise, they're all single-dimensional. It's only the cleverness of pointer arithmetic (striding the pointer by the size of a row) that gives you the functionality of extra dimensions. A jagged array laid out serially has different row sizes, so it cannot be strode by a constant value, so it requires additional storage depending on data size, thus is impossible to express in C type system.
It becomes clearer when you consider to what pointer multidimensional array decay to: Array to pointer decay and passing multidimensional arrays to functions
And that's why you see the error message must have bounds for all dimensions except the first, because all dimensions except the first are necessary to stride the array.