I'm practicing C++ vector and as an exercise I want to fill a vector with 16 million random numbers and then find the position of the first occurrence of a number. The code which I implemented so far is this:
int getIndexOf(std::vector<int>& v, int num) {
for(std::size_t i=0; i < v.size(); i++) {
if(v.at(i) == num) {
return i;
}
}
return -1;
}
int main() {
int searchedNumber = 42;
int vectorSize = 16000000;
std::vector<int> v(vectorSize);
for(std::size_t i=0; i < v.size(); i++) {
v.push_back(rand() % 10000000);
}
//Linear search
auto start = std::chrono::high_resolution_clock::now();
int position = getIndexOf(v, searchedNumber);
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
std::cout << "The linear search took: " << duration.count() << " seconds" << std::endl;
std::cout << "The number " << searchedNumber << " occur first at position " << position << std::endl;
return 0;
}
Additionally I measure the time just for some statistics. The problem is that the program crash with error bad_alloc which I link with Running out of stack space. So initially I though that filling a vector with so many numbers when the vector is on the stack will be a reason for the crash and I created the vector dynamically (pointer). However, I still get the same error. What might be the reason for this?
int vectorSize = 16000000;
std::vector<int> v(vectorSize);
for(std::size_t i=0; i < v.size(); i++) {
v.push_back(rand() % 10000000);
}
This part is bad. push_back() adds an element to the vector, so it increases size(). Therefore, this loop won't terminate until something bad happens.
You should do like this instead:
int vectorSize = 16000000;
std::vector<int> v;
v.reserve(vectorSize); // allocate memory without actually adding elements
for(int i=0; i < vectorSize; i++) { // use the known size
v.push_back(rand() % 10000000);
}
Related
So I have an array as :
arr[] = {5, 2,4,2,3,5,1};
How can I insert them in this order with the number of times they occur in unordered_map?
#include<bits/stdc++.h>
using namespace std;
void three_freq(int arr[], int n){
unordered_map<int, int> m;
for(int i=0;i<n;i++){
m[arr[i]]++;
}
for(auto itr = m.begin(); itr != m.end(); itr++){
cout<<itr->first<<":"<<itr->second<<"\n";
}
}
int main(){
int arr[] = {5, 2,4,2,3,5,1};
int n = sizeof(arr)/ sizeof(arr[0]);
three_freq(arr, n);
return 0;
}
Using the code above I am getting output as :
1:1
3:1
4:1
5:2
2:2
But I want the output to be in same order as the element occur in array.
Example:
5:2
2:2
4:1
3:1
1:1
If you don't care about efficiency (that much), then you can just change the for loop which is printing the output.
for(int i=0; m.size(); i++) {
auto it = m.find(arr[i]);
if (it != m.end()) {
cout<<arr[i]<<":"<<it->second<<"\n";
m.erase(it);
}
}
The quite efficient way is traversing the original array and resetting the counters after print.
for (int i = 0; i < n; ++i) {
if (m[a[i]]) != 0) {
std::cout <<arr[i] << ":" << m[a[i]] << std::endl;
m[a[i]] = 0;
}
}
You need unordered_map to do the counting efficiently, so keep that.
When printing out according to the order in another container, it makes sense to simply iterate over that other container for your output loop.
(Note that this is a completely separate operation, so it could have been a different function.)
// loop over the original array (recommend std::vector)
// exit early if done (stole from fadedreamz)
for (int index = 0; !m.empty(); ++index) {
int number = arr[index];
// check to see if we need to print this number
// use contains if you have c++20
if (m.count(number)) {
std::cout << number << ":" << m[number] << std::endl;
m.erase(number); // print only once by deleting the entry
}
}
So Here is the question:
Consider a class named Job that has deadline as a data member and relevant getter/setter
method(s). Assume you have to schedule two most earliest jobs on the basis of their deadlines. That is,
if there are three jobs in the system with deadlines (deadline1, deadline2, and deadline3, respectively)
then the system should report the top two earliest jobs (with smallest deadline value). You might need
to find the deadline with smallest and second most smallest value.
Here is my code:
#include<iostream>
using namespace std;
class job
{
private:
int Deadline;
public:
static int i;
void setDeadline(int a);
int getDeadline();
};
void job::setDeadline(int a)
{
Deadline = a;
cout << "Job " << i << " Has Deadline " << Deadline << endl;
}
int job::getDeadline()
{
return Deadline;
}
int job::i = 1;
int main()
{
job job1, job2, job3, job4, job5, job6, job7, job8, job9, job10, count;
job1.setDeadline(5);
count.i++;
job2.setDeadline(3);
count.i++;
job3.setDeadline(6);
count.i++;
job4.setDeadline(12);
count.i++;
job5.setDeadline(31);
count.i++;
job6.setDeadline(20);
count.i++;
job7.setDeadline(19);
count.i++;
job8.setDeadline(2);
count.i++;
job9.setDeadline(8);
count.i++;
job10.setDeadline(7);
int array[10] = { job1.getDeadline(), job2.getDeadline(),job3.getDeadline(),job4.getDeadline(),job5.getDeadline(),job6.getDeadline(),job7.getDeadline(),job8.getDeadline(),job9.getDeadline(),job10.getDeadline() };
int temp = array[0], store = 0, first = 0, second = 0;
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
}
}
for (int i = 0; i <= 9; i++)
{
if (temp == array[i])
{
first = i + 1;
break;
}
}
temp = array[0];
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
}
}
for (int i = 0; i <= 9; i++)
{
if (temp == array[i])
{
second = i + 1;
}
}
cout << "\nJob " << first << " and Job " << second << " are earliest";
return 0;
}
the problem I am facing is that both times it print the first smallest value. I want to print first 2 smallest value. How can I do that?
When you look for the first value, you go through the array and find the job with the lowest deadline and fill "first" with the job id (by the way, if you want to relate the "job id" to the index, personally I would make the variables zero-based, so job0, job1 and so on up to job9)
When you look for the second value, you do the exact same operations so the job you find is again the job with the lowest deadline and use that info to fill "second".
So, as you do the exact same thing both times, you are getting the exact same value for both. When you search for the second value you should take "first" into account so that you ignore the job that has already been used for "first" and not update "temp" in that case (this is a little bit easier if you name the jobs starting with zero because you don't have to constantly add one to the index).
the problem I am facing is that both times it print the first smallest value. I want to print first 2 smallest value. How can I do that?
With your solution: By creating another temp array with the first element removed you already discovered.
I wrote you as a minimal executable example using a vector of pairs since you didn't mention restrictions or anything - that is the most elegant solution I am able to come up with:
#include <iostream>
#include <vector>
#include <string>
bool sortVecBySec(const std::pair<std::string, int> &a,
const std::pair<std::string, int> &b)
{
return (a.second < b.second);
}
int main()
{
//Driver function to sort the vector elements by
//the second element of pairs
std::vector<std::pair <std::string,int>> v;
std::string job[10];
int deadline[10] = {5,3,6,12,31,20,19,2,8,7};
int n = sizeof(job)/sizeof(job[0]);
//Propagate string array
for(int i{}; i < 10;++i){
job[i] = "Job " + (std::to_string(i+1));
}
//Enter values in vector of pairs
for(int i{}; i<n; ++i){
v.push_back(make_pair(job[i],deadline[i]));
}
//Printing the vector of pairs
std::cout << "Vector of pairs as it is before\n";
for(int i{}; i< n; i++){
std::cout << v[i].first << " = " <<v[i].second << '\n';
}
//Using sort() function to sort by 2nd element of pairs
sort(v.begin(), v.end(),sortVecBySec);
//Printing the vector of pairs
std::cout << "\nVector of pairs from shortest to longest\n";
for(int i{}; i< 2; i++){
std::cout << v[i].first << " = " <<v[i].second << '\n';
}
std::cin.get();
return 0;
}
If you want to print all jobs, just use the n variable in the last print section instead of 2.
I think that should help you and shouldn't be to hard to parse it in a class.
First, you can save an extra round by saving the index right there, when you locate the earliest deadline
for (int i = 0; i <= 9; i++)
{
if (temp > array[i])
{
temp = array[i];
first = i + 1;
}
}
When searching for the next higher deadline value, you must take first into account. Both for the start value, and later when comparing with other values
temp = first > 1 ? array[0] : array[1];
for (int i = 0; i <= 9; i++)
{
if (temp > array[i] && array[i] > array[first])
{
temp = array[i];
second = i + 1;
}
}
Be aware, that this does not work properly, when you have multiple equal values.
For this case, compare the index values instead, e.g.
if (temp > array[i] && i != first)
{
temp = array[i];
second = i + 1;
}
I have no error message instead I only have unexpected behavior.
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
x = make_pair(values[i]/weights[i], weights[i]);
valuePerWeight.push_back(x);
}
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
double value = 0.0;
return value;
}
I am creating a vector with values of type pair<double,int>. I create the pair using make_pair(some_double, some_int), then I call push_back with the pair.
Later in the function I index into the vector and do stuff using the pairs.
However an issue arises, when I index into my valuePerWeight vector and retrieve the attributes of the different pairs. They all end up being zero regardless of index and regardless of .first or .second.
Through printing a bunch of variables I have asserted the created pair is not {0,0} but as soon as I push_back into the vector and index the pair and look at it's .first and .second attributes both are equal to 0.
I can't seem to understand why this is, originally I was using push_back seen as below
valuePerWeight.push_back(make_pair(values[i]/weights[i], weights[i]));
instead of creating into a temporary variable x . However the same issue still stands.
Any help in the right direction would be greatly appreciated.
If there is any further clarification that I can give please ask me.
If you'd like to see for some values below is a snippet which can be compiled
I use input
3 50
60 20
100 50
120 30
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
double value = 0.0;
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
cout << v << ' '<< weights[i] << '\n';
x = make_pair(values[i]/weights[i], weights[i]);
cout << x.first << ' ' << x.second << '\n';
valuePerWeight.push_back(x);
cout << valuePerWeight[i].first << ' ' << valuePerWeight[i].second << '\n';
}
for(int i = 0; i < n; i++){
cout << valuePerWeight[i].first;
cout << valuePerWeight[i].second;
cout << '\n';
}
sort(valuePerWeight.begin(), valuePerWeight.end());
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
// for(auto vp: valuePerWeight){
// cout << vp.first << vp.second;
// cout << '\n';
// }
return value;
}
int main() {
int n;
int capacity;
std::cin >> n >> capacity;
vector<int> values(n);
vector<int> weights(n);
for (int i = 0; i < n; i++) {
std::cin >> values[i] >> weights[i];
}
double optimal_value = get_optimal_value(capacity, weights, values);
std::cout.precision(10);
std::cout << optimal_value << std::endl;
return 0;
}
The confusion here is due to the behavior of the constructor you use
vector<pair<double, int>> valuePerWeight(n);
This actually fills the vector with n default constructed pairs, which as you may surmise, are (0, 0). When you push_back, you push to the end of these, so you a totally get 2n pairs.
.reserve does something close to what you expected, not actually filling the vector, but is likely not needed for something not bottle-necking on vector resizing.
Short story, omit the (n) to just construct an empty vector.
Three more suggestions: accept the vectors as const& to save a copy, and look at emplace_back instead of making a pair yourself and pushing it. That's what it's meant for. Also, note the comment by churill - dividing two integers will result in integer division regardless of where you are assigning the result. Static cast one of them to a float or double (or multiply by 1.0 at the start) to ensure floating point division.
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;
}
With the help of SO members, the following program successfully converts a static 1D array into a 2D vector by considering below criteria:
Each time an element with value = 0 is encountered, a new row is created. Basically when a 0 is encountered, row value is increased and column value is reset to 0. If a non-zero value is encountered, the row value is maintained and column value is increased.
// declarations
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
std::vector<int>::size_type j;
std::vector<int>::size_type i;
vector<vector<int>> my2dArray;
vector<int> dArray;
void calc(vector<int>&, int);
int task;
int sum = 0;
int main() {
for (int i = 0; i < 9;
i++) // iterate through all elements of the given array
{
if (i == 0) // adding the first element
{
my2dArray.resize(my2dArray.size() + 1);
my2dArray.back().push_back(givenArray[i]);
continue;
}
if (givenArray[i] == 0) // re-size if 0 is encountered
{
my2dArray.resize(my2dArray.size() + 1);
}
my2dArray.back().push_back(givenArray[i]);
}
for (std::vector<std::vector<int>>::size_type i = 0; i < my2dArray.size();
i++) {
for (std::vector<int>::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
if (my2dArray[i].size() > 2) {
task = my2dArray[i].size();
calc(my2dArray[i], task);
}
}
std::cout << std::endl;
}
}
void calc(vector<int>& dArray, int task) {
int max = 0;
for (unsigned int j = 0; j < task; j++) {
if (dArray[i] > max)
dArray[i] = max;
}
cout << "\nMax is" << max;
}
However, I want to pass a single row of 2D vector 2dArray to function calc if the number of columns for each row exceeds 2. Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Some improvements:
i and j global variables are not needed, you are declaring the variables of the loops in the loop initialization (ex: for (int i = 0; i < 9; i++), the same for the other loops).
It's better not to used global variables, only when strictly necessary (with careful analysis of why). In this case it's not necessary.
The typedef are for more easy access to inner typedef of the type (ex: size_type).
You were doing the call to calc method in every iteration of the inner loop, and iterating over the same row multiple times, this call should be executed once per row.
Using the size of array givenArray as constant in the code is not recommended, later you could add some elements to the array and forgot to update that constant, it's better to declare a variable and calculated generally (with sizeof).
There is no need to pass the size of the vector to method calc if you are passing the vector.
As recommended earlier it's better to use std::max_element of algorithm header.
If you could use C++11 the givenArray could be converted to an std::vector<int> and maintain the easy initialization.
Code (Tested in GCC 4.9.0)
#include <vector>
#include <iostream>
using namespace std;
typedef std::vector<int> list_t;
typedef std::vector<list_t> list2d_t;
void calc(list_t& dArray, long& actual_max) {
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
void calc(list_t& dArray) {
long actual_max = 0;
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
int main() {
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
int givenArraySize = sizeof(givenArray) / sizeof(givenArray[0]);
list2d_t my2dArray(1);
list_t dArray;
for (int i = 0; i < givenArraySize; i++) {
if (givenArray[i] == 0) {
my2dArray.push_back(list_t());
} else {
my2dArray.back().push_back(givenArray[i]);
}
}
long max = 0;
for (list2d_t::size_type i = 0; i < my2dArray.size(); i++) {
for (list_t::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
}
std::cout << "\n";
if (my2dArray[i].size() > 2) {
// if you need the max of all the elements in rows with size > 2 uncoment bellow and comment other call
// calc(my2dArray[i], max);
calc(my2dArray[i]);
}
}
}
Obtained Output:
1 2 3
Max is 3
4
1 2 1
Max is 2
You have a few problems:
You don't need to loop over j in the main function - your calc function already does this.
Your calc function loops over j, but uses the global variable i when accessing the array.
Your calc function assigns the current max value to the array, rather than assigning the array value to max
Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Instead of writing a function, you could have used std::max_element.
#include <algorithm>
//...
int maxVal = *std::max_element(my2dArray[i].begin(), my2dArray[i].begin() + task);
cout << "\Max is " << maxVal;