Derive the execution time growth rate (BigO) of the following code - c++

What is execution time growth rate Big O of this code?
void doDiff(int setA[], int setB[], int sizeA, int sizeB) {
const int MAX = 10;
// validate setA and setB
if ((sizeA == 0) && (sizeB == 0))
cout << "both sets are empty " << endl;
else
cout << "symmetric difference: { " ;
for (int i = 0; i < sizeA; i++ )
if (!member(setB, setA[i],sizeB))
cout << setA[i] << " ";
for (int i = 0; i < sizeB;i++ )
if (!member(setA, setB[i],sizeA))
cout << setB[i] << " ";
cout << "}" << endl;
}
bool member(int set[], int n, int size)
{
for (; size > 0; size--)
if (set[size-1] == n)
return true;
return false;
}
When I calculate the big O of this code, I end up with O(N*N*N) || O(N^3)
I am not sure what exact execution time growth rate is for this code.
please help me.
Thank you in advance

It seems inappropriate to fill an answer with questions, but since this sounds like homework, I think they're a better way to the goal (which is for YOU to figure out how this works):
What is the "big-O" of member? This is important, since doDiff relies on it so much.
How many times does doDiff call member?
If every call to member takes the same amount of time, member is O(X), and doDiff calls member Y times, what is the "big-O" of doDiff?

Related

Find the smallest value in a vector

I am pretty new when it comes to programming with STL and I thought I was getting the hang of it. But I am a little perplexed about this one bit. My goal is to take in 5 values, then print out my values, print the highest value among them, print the average, and print the lowest among them ( my problem ). It seems that my variable "low" is given the value of 0 and I do not know why this is. I have tested to see if my values are being read in and to my knowledge, they are. So if anyone could please enlighten me to why I cannot seem to get the proper lowest value, I would greatly appreciate it. Thank you for your time.
vector<double> vecList;
int x = 0;
double high = 0;
double low = 0;
double sum = 0;
cout << "Enter Integer Values, then press Ctrl(z) to Quit:" << endl;
for (int i=0; i < 5; i++)
{
cin >> x;
sum = sum + x;
vecList.push_back(x);
}
vector<double>::iterator intVecIter;
cout <<"List contains: ";
for (intVecIter = vecList.begin(); intVecIter != vecList.end(); ++intVecIter)
cout << *intVecIter << " ";
for (int i=0; i < 5; i++)
{
if(vecList[i] > high)
{
high = vecList[i];
}
// prints out "0"
if(low > vecList[i])
{
low = vecList[i];
}
}
cout << endl << "Largest: "<< fixed << setprecision(2) << high << endl;
cout << "Smallest: "<< fixed << setprecision(2) << low << endl;
cout << "Average: " << fixed << setprecision(2)<< (sum/5);
return 0;
Since you are trying to learn STL, take a look at the algorithms library and it has some helper functions which will give the min, max and sum (accumulate is the actual function name) for a given range.
you need to initalize low to a big value not 0, otherwise this
if(low > vecList[i])
is never true

Mysterious Stack Overflow

So I wrote a program that utilizes the euclid algorithm to find GCD's of 2 ints.
The user enters one int (n), then the program takes every possible integer combination between 8 and n, finds their respective GCD's (recursively), and prints which GCD calculations required the most modulus operations.
I got the program working, but I get a stack overflow at around n=50, and it needs to work to at least 3000.
I've reviewed my code for a while and cannot find the problem.
#include<iostream>
#include <math.h>
using namespace std;
int cost, gcd, greatestCost, n, beginningA, beginningB, finalA, finalB, finalGCD, iteration;
void findGCD(int num1, int num2, int startingCost) {
//findGCD
//finds GCD of every combination (a,b) from i to n
//prints those with the greatest number of modulus operations
int a = num1;
int b = num2;
cost = startingCost;
cost++;
if (b%a > 0) {
//cout << "gcd(" << b << "," << a << ") = ";
findGCD(b%a, a, cost);
}
else {
gcd = a;
if (cost > greatestCost) {
greatestCost = cost;
finalA = beginningA;
finalB = beginningB;
finalGCD = gcd;
}
//cout << "gcd(" << b << "," << a << ") = " << gcd << " With a cost of: " << cost << endl;
//do next iteration (2,8), (3,8) etc...
if (++beginningA <= beginningB) { //beginning A goes from 1-i first
findGCD(beginningA, beginningB, 0);
}
else {
if (beginningA <= n) { //begin next cycle with new b value (1,9), (2,9) while b <= n
beginningA = 1; //reset to 1 so it will increment from 1-i again
cout << "At i=" << iteration++ << "; gcd(" << finalA << "," << finalB << ") = " << finalGCD <<
" took " << greatestCost << " modulus operations" << endl;
findGCD(beginningA, ++beginningB, 0);
}
else //When it tries to continue iterating with a number > n
//print the last, most intensive, iteration and stop
cout << "At i=" << iteration++ << "; gcd(" << finalA << "," << finalB << ") = " << finalGCD <<
" took " << greatestCost << " modulus operations" << endl;
}
}
}
int main() {
greatestCost = 0; //cost of the iteration with the most modulus operations
beginningA = 1;
beginningB = 8;
iteration = 8;
cout << "Enter an integer greater than 8 " << endl; //receive n from user
cin >> n;
if (n <= beginningB) //begin GCD search, granted user input > 8
cout << "Error!!! integer must be greater than 8";
else
findGCD(beginningA, beginningB, 0); //algorithm begins at (1,8)
return 0;
}
At this point the only thing I can think of as the problem is something I've done in C++ that I shouldn't (I am new to C++ and transferred over from java)
Sample Output
Things I've tried:
splitting the gcd function into 2
passing only references through the functions
First of all your explanation is unclear, from you code I understood that for every 8<=i<=n you take all possible x, y where y<=i and x<=y and calculate which gcd require most steps.
I've rewritten your code so that findGCD only finds gcd of 2 number, while incrementing some global cost variable.
#include<iostream>
#include <math.h>
using namespace std;
int cost, gcd, greatestCost, n, beginningA, beginningB, finalA, finalB, finalGCD, iteration;
int findGCD(int a, int b) {
cost++;
if (b%a > 0)
return findGCD(b%a, a);
else
return a;
}
int main() {
greatestCost = 0; //cost of the iteration with the most modulus operations
beginningA = 1;
beginningB = 8;
iteration = 8;
cout << "Enter an integer greater than 8 " << endl; //receive n from user
cin >> n;
if (n <= beginningB) //begin GCD search, granted user input > 8
cout << "Error!!! integer must be greater than 8";
else {
for ( int i = beginningB; i <= n; i++ ) {
int greatestCost = 0, gcd0 = 1, i0 = 0, j0 = 0;
for ( int t = beginningB; t <= i; t++ )
for ( int j = 1; j <= t; j++ ) {
cost = 0;
int gcd = findGCD(j, t);
if ( cost > greatestCost ) {
greatestCost = cost;
gcd0 = gcd;
i0 = t;
j0 = j;
}
}
cout << "At i=" << i << "; gcd(" << j0 << "," << i0 << ") = " << gcd0 <<
" took " << greatestCost << " modulus operations" << endl;
}
}
return 0;
}
The stack overflow you're getting is caused by using too deeply recursive calls: Every time you call a function a new stack frame (holding local variables, parameters and possibly other stuff) is created in the (call) stack. This frame is freed only when returning (normally or via exception) from the function. But with recursive calls you don't return from the first function call before returning from the second, which in turn only returns after the third and so on. Thus stack frames are piling up on the stack, which is commonly about the size of around 8 kB, until all available memory for the stack is used: That's the stack overflow (you put too much on it, thus it overflows).
This can be solved by using iteration (using loops) instead:
An outer one incrementing from 8 up to the user supplied maximum, as well as an inner one incrementing from 0 to the value of the outer loop's current iteration variable. This gives you all the pairs of values you want to operate on.
Calculating the greatest common divisor and its cost should be factored out into a function.
The only thing left is calling that function from within the loops and some how keeping track of the maximum.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
unsigned gcd(unsigned a, unsigned b, unsigned * const cost) {
if (cost) {
*cost = 0;
}
while (b != 0) {
auto const rest = a % b;
if (cost) {
++(*cost);
}
a = b;
b = rest;
}
return a;
}
int main() {
unsigned const n = 3500;
unsigned greatestCost = 0;
vector<pair<unsigned, unsigned>> pairs;
for (unsigned b = 8; b <= n; ++b) {
for (unsigned a = 0; a <= b; ++a) {
unsigned cost;
gcd(a, b, &cost);
if (cost == greatestCost) {
pairs.emplace_back(a, b);
} else if (cost > greatestCost) {
pairs.clear();
pairs.emplace_back(a, b);
greatestCost = cost;
}
}
}
cout << "Greatest cost is " << greatestCost << " when calculating the GCD of " << endl;
for (auto const & p : pairs) {
cout << "(" << p.first << ", " << p.second << ")" << endl;
}
return 0;
}
(Live)
Note in particular that I'm not using any global variable.
The above might make you feel that recursion is an unusable, useless construct. This is not the case. Many algorithms are most cleanly expressed using recursion. When putting the recursive call as the last statement, then an optimisation known as tail call optimisation can be used: Then the called function is reusing the stack frame of the calling function, thus not using any more memory.
Unfortunately this optimisation is quite tricky to implement in a language like C++ due to various reasons.
Other languages, mostly functional ones, use it and thus also recursion instead of loops, though. An example of such a language is Scheme, which even requires implementations to be able to make that aforementioned optimisation.
As a final note: You could implement the GCD calculation using recursive calls here, since as you see the maximum depth will be 17 + 1 which should be small enough to fit on any (outside of embedded systems) call stack. I'd still go with the iterative version though: It has better performance, better fits the idiom of the language and is the "safer" way to go.

Entering 20 numbers into an array with no duplicates

int main()
{
int theArray [20] = {0};
int userInput = 0;
int populateCount = 0;
cout << "Enter 20 integers between 10 and 100 inclusive. " << endl;
while (populateCount < 20)
{
cin >> userInput;
theArray[populateCount] = {userInput};
if (userInput<10||userInput>100)
{
cout << "That is not a legal input. " << endl;
populateCount - 2;
}
else
{
populateCount++;
}
}
cout << "\n";
for (int i = 0; i < 20; i++)
{
cout << theArray[i] << endl;
}
}
I've got the baseline of my code done. The user enters twenty numbers and they're added to the array. If it's less than 10 or greater than 100 it's not a legal input, I subtract from the count, and they're allowed to go again. Then after the user finishes plugging in numbers it prints the array. However, I've been trying different if statements inside the array to eliminate duplicates, such as (if theArray[i] == theArray[i+1] then [i+1] = 0) I suppose that could work if I incorporated a sort to get all the 0's at the end, but is there a more efficient way to do this?
Before I go to the answer I suggest we clean it up slightly to make the problem more clear and remove other confusion.
Misconception
The statement populateCount - 2 has no effect.. instead you are simply not incrementing populateCount which is why the loop doesn't advance.
I would suggest something of this format within the loop. It puts the 'happy' path first, which will also make for some clearer ways to handle the second part.
if (userInput >= 10 && userInput <= 100 ) {
theArray[populateCount++] = userInput;
}
else {
std::cout << userInput << " is not legal input, must enter value "
<< "between 10 and 100. " << std::endl;
}
Preface
Before we attack the problem first let's refactor so that we can break it down to a single function so that as we work we don't disturb everything else as well as gain flexibility for testing and simplify readability.
Refactor
/* this code is responsible for doing what is needed to
* only insert unique items */
bool insert( const int& input, int* array, int num_elements ) {
// the fun part!
// more to follow shortly
};
/* gets user input forcing input to be between min and max */
int getUserInput(int min, int max) {
bool found = false;
int result = 0;
/* this can be done with less code but this makes it easy
* to see whats going on */
while ( !found ) {
cout << "Please enter a value between " << min << " and " << max << "." << endl;
cin >> result;
if ( result >= min && result <= max ) {
found = true; //yes we could break or return from here
} else {
cout << result << " invalid. "<< endl;
}
}
return result;
};
void printArray( const int* array, const int& size ) {
for (int i = 0; i < size; i++)
{
cout << array[i] << endl;
}
};
int main()
{
const int totalElements = 20;
int theArray [totalElements] = {0};
int userInput = 0;
int populateCount = 0;
int minVal = 10;
int maxVal = 100;
cout << "Enter " << totalElements << " integers between "
<< minVal << " and " << maxVal << " inclusive. " << endl;
while ( populateCount < numElements )
{
//this will percievably loop until it's good
userInput = getUserInput(minVal, maxVal);
if ( insert( userInput, theArray, populateCount ) )
++populateCount; //increments if we did insert it
}
}
cout << endl;
printArray( theArray, totalElements );
}
Attacking the problem
Ok so now our problem is simple, we just have to write the insert function. There are a couple of choices here, you can check each element in turn which as you said can be slow, O(n), or we could sort the array to make it quick, O(log n) + cost of sorting. Other possibilities I presume aren't available are using a std::set instead of an array, or using STL to do the work of sorting and finding. Note that in these modes insert won't actually do an insertion if the number is already present.
Another unique idea is to use an array of bools size max-min, and simply flag the index of input-min as true when you find it. This will be fast at the cost of size depending upon the gap between min and max. (this is essentially a hash function)
The advantage we are at from a refactor is that you can in turn write and try each of these solutions and even feed them the same canned input now that we've refactored so that you can try and time each one. For timing I would heavily suggest you add lots of numbers and consider greatly expanding the min and max to understand the scalability of each choice

Population program in C++

I'm in desperate need of assistance.
I'm working on a population program in C++ for my Systems Software class.
This is my first foray into C++ territory, I only have some Java knowledge to help me out.
Basically, the program is supposed simulate a simple population. The guidelines are as follows:
The first elements (starting population) have random age and sex.
2 elements can pair if their lifespan falls between [0.25,0.50] (assuming they die at 1) and they are of the opposite sex.
Each element can only pair twice.
So here's my code, and take it easy guys I'm not very well versed in C++ yet...:
#include <vector>
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <iterator>
using namespace std;
class Element {
public:
int pair;
double life;
int tag;
void setValues(double, int);
int getPair() {
return pair;
}
void incrementPair() {
pair = pair++;
}
double getLife() {
return life;
}
void incrementLife() {
life = life + 0.05;
}
int getTag() {
return tag;
}
}; //Element
void Element::setValues(double b, int c) {
pair = 0;
life = b;
tag = c;
}
int main() {
double Time = 0.0;
srand(time(NULL));
vector<Element> vec;
for (int i = 0; i<50; ++i) {
Element x;
x.setValues(((double) rand() / (RAND_MAX)), rand()%2);
vec.push_back(x);
}//for
while (vec.size() != 0) {
int newPopCount = 0;
int Dead = 0;
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
if ((p->getPair() == 2) || (p->getLife() < 0.25) || (p->getLife() > 0.50)) {
count++;
p++;
}//if
else {
for(int count1 = count + 1 ; count1 != vec.size() ; ) {
if ((i->getLife() < 0.25) || (i->getLife() > 0.50) || (i->getPair() == 2) || (p->getTag() == i->getTag())) {
++i;
count1++;
}//if
else {
cout << i->getTag() << " " << p->getTag() << endl;
cout << i->getPair() << " " << p->getPair() << endl;
cout << i->getLife() << " " << p->getLife() << endl;
p->incrementPair();
i->incrementPair();
newPopCount++;
count1++;
count++;
p++;
i++;
}//else
}//for
}//else
}//for
Time += 0.05;
for ( vector<Element>::iterator m = vec.begin(); m != vec.end(); ++m ) {
m->incrementLife();
if ( m->getLife() >= 1.00 ) {
Dead++;
//vec.clear();
vec.erase(m);
//vec.shrink_to_fit();
}//if
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}//for
}//for
cout << "The total number of dead is: " << Dead << endl;
cout << "The total number born is: " << newPopCount << endl;
cout << "Current population is: " << vec.size() << endl;
cout << "Population has survived for: " << Time << endl;
sleep(1);
}//while
cout<< "The populace is now extinct." << endl;
cout<< "The populace survived for: " << Time << endl;
}//main
You can see my silly debugging methods, I was getting a Segmentation Fault error before, but I believe that to be fixed. The issue now is that I'm getting stuck in the loops. The program seems to run almost erratically, and I can't pinpoint the issue any closer than inside of one of the loops.
My Dead integer is incremented and displayed properly, but the newPopCount integer is not, which makes no sense to me.
Also the program never gets out of the while loop, it will continue until it gets stuck in another of the many loops I have.
I have had several other issues, which I've been fixing slowly but surely as you can see by my patchwork code.
Any help at all will be greatly appreciated.
Two obvious issues, which your compiler will warn you about if you turn up your warnings high enough.
First:
void incrementPair() {
pair = pair++;
}
This is undefined behavior. Should be just:
void incrementPair() {
++pair;
}
Second:
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}
That condition in your for loop is almost certainly wrong. It likely should be i <= newPopcount, or something like that.
As a side note, your setValues() member function looks like it's doing the job that a constructor should be doing.
EDIT: Look here:
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
Imagine you have a std::vector with only one element in it, and then think about what i is going to represent when you do i->getLife() a few lines later. Just having those definitions inside the for loop looks a bit suspicious in itself, since you increment both p and i during the loop, but you're going to reset them again on every iteration, but it's not all that easy to follow the logic, so perhaps that's what you intended.
vec.erase(m); results in an invalid m. You want to do m = vec.erase(m)

How to refactor this simple code to avoid code duplication?

I am solving the following simple problem(on one of OnlineJugde sites which is in Russian, so I won't give a link here:). It is easier to state the problem via an example than definition.
Input:
10 // this is N, the number of the integers to follow
1 1 1 2 2 3 3 1 4 4
Output:
3 times 1.
2 times 2.
2 times 3.
1 times 1.
2 times 4.
Constraints:
All the numbers in the input(including N) are positive integer less than 10000.
Here is the code I got Accepted with:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int prevNumber = -1;
int currentCount = 0;
int currentNumber;
while(n --> 0) // do n times
{
cin >> currentNumber;
if(currentNumber != prevNumber)
{
if(currentCount != 0) //we don't print this first time
{
cout << currentCount << " times " << prevNumber << "." << endl;
}
prevNumber = currentNumber;
currentCount = 1;
}
else //if(currentNumber == prevNumber)
{
++currentCount;
}
}
cout << currentCount << " times " << prevNumber << "." << endl;
}
Now here's my problem. A little voice inside me keeps telling me that I am doing this line two times:
cout << currentCount << " times " << prevNumber << "." << endl;
I told that voice inside me that it might be possible to avoid printing separately in the end. It told me that there would then be perhaps way too many if's and else's for such a simple problem. Now, I don't want to make the code shorter. Nor do I want do minimize the number of if's and else's. But I do want to get rid of the special printing in the end of the loop without making the code more complicated.
I really believe this simple problem can be solved with simpler code than mine is. Hope I was clear and the question won't be deemed as not constructive :)
Thanks in advance.
i came up with this. no code duplication, but slightly less readable. Using vector just for convenience of testing
EDIT my answer assumes you know the numbers ahead of time and not processing them on the fly
vector<int> numbers;
numbers.push_back(1);
numbers.push_back(1);
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(2);
numbers.push_back(3);
numbers.push_back(3);
numbers.push_back(1);
numbers.push_back(4);
numbers.push_back(4);
for (int i=0; i<numbers.size(); i++)
{
int count = 1;
for (int j=i+1; j<numbers.size() && numbers[i] == numbers[j]; i++, j++)
{
count++;
}
cout << count << " times " << numbers[i] << "." << endl;
}
My version: reading the first value as a special case instead.
#include <iostream>
int main()
{
int n;
std::cin >> n;
int value;
std::cin >> value;
--n;
while (n >= 0) {
int count = 1;
int previous = value;
while (n --> 0 && std::cin >> value && value == previous) {
++count;
}
std::cout << count << " times " << previous << ".\n";
}
}
Run your loop one longer (>= 0 instead of > 0), and in the last round, instead of reading currentNumber from cin, do currentNumber = lastNumber + 1 (so that it's guaranteed to differ).
slightly more CREATIVE answer, this one does not make assumption about input being all known before the start of the loop. This prints the total every time, but makes use of \r carriage return but not line feed. A new line is inserted when a different number is detected.
int prev_number = -1;
int current_number;
int count = 0;
for (int i=0; i<numbers.size(); i++)
{
current_number = numbers[i];
if (current_number != prev_number)
{
count = 0;
cout << endl;
}
count++;
prev_number = current_number;
cout << count << " times " << numbers[i] << "." << "\r";
}
only problem is that the cursor is left on the last line. you may need to append cout << endl;
I think this will work:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int prevNumber = -1;
int currentCount = 0;
int currentNumber;
int i = 0;
while(i <= n)
{
if(i != n) cin >> currentNumber;
if(currentNumber != prevNumber || i == n)
{
if(currentCount != 0)
{
cout << currentCount << " times " << prevNumber << "." << endl;
}
prevNumber = currentNumber;
currentCount = 1;
}
else
{
++currentCount;
}
i++;
}
}
I would use a for loop, but I wanted to stay as close to the original as possible.