How to estimate the runtime when the input size is unknown - algorithm

I am learning how to analyze the algorithm (First 5 chapters) by myself using this book: Introduction of Algorithms. Assume I have the following simple algorithm (I made it up):
for i <- 0 to 100
for j <- 1 to 2000
if (i*10 + j*20 = n)
c <- c+1
Now, if I want to estimate the running time of this algorithm for a specific input size, say n= 500, I'd say:
The running time in worst case is T(n) = 100*2000*500 = 10 * 10^7. However, when I want to generalize for any input size, i.e. n, I don't know how to do this! Kindly, can someone enlighten me?
Thank you

Your current running time is wrong. Since you always loop through all i and j values, it takes a total of 100*2000 iterations. This is independent of your n value. However, if you assume your unknowns are the max i and j values, denoted by I and J respectively, you could say your algorithm has running time O(IJ). You're on the right track, just replace your constants for variables.

Related

How to calculate time complexity of existing code in production [duplicate]

This question already has answers here:
Big O, how do you calculate/approximate it?
(24 answers)
Closed 2 years ago.
I have gone through a couple of examples in understanding the time complexity of a program using the operation count and step count technique but these examples are small and straight. However in real-world programming, if someone gives you the production or live code to find the worst case time complexity of it. How does one start analyzing it?
Is there any technique or thumb rules for analyzing the program? say I have a function as shown below that has if and for conditions. For some values of n, it goes deep but for some values, it does not.
So maximum number of operations is the worst case and the minimum number of operations is the best case.
How can we know when do maximum operations occur if we have this kind of conditional statement? (Other functions can go much deeper conditional and not the loops)
int l = 0;
while (l <= n){
int m = l + (n-l)/2;
if (arr[m] == x) return;
if (arr[m] < x) l = m + 1;
else n = m - 1;
}
How does one calculate the worst and best case by looking at the above code? Do the perform step count for the above program and by substituting n = 1 till 20 and get some values and then trying to derive the function? I would like to know how do people analyze time complexity for existing code when they have this kind of branching statements.
Step by Step analysis or Set of statements to follow to solve the above problem would be greatly helpful.
As each time half of the n is added to m and the loop will be continued by increasing a unit of l or changing the value of the n to the m-1 the following scenario can give the maximum operation:
In each iteration, the `else` part is happened and set `n` to `m-1`.
Let see what is happened for this case. As each time n is dividend by 2, and l is keeping 0, after O(log(n)) iteration, l == n.
Therefore, the time complexity of the loop is O(log(n)).
Notice that other cases can increase l faster towards n. For example, if l = m + 1 it means that l = (n-1)/2, and in the next iteration, m will be increased to n-1. Hence, just 2 iteration we will have to reach to the end of the loop.

Can we use probabilities to determine whether an algorithm is non-terminating?

My question isn't about some specific code but rather theoritical, so my apologies in advance if that's not the right place to post it.
Given a certain problem - for the sake of discussion, let it be a permutation problem - with an input of size N, and P the constant time needed to calculate 1 permutation; in this case, we need about T = ~ (P)*(N!) = O(N!) time to produce all results. If by any chance our algorithm takes much more than the expected time, it may be safe to assume it doesn't terminate.
For example, for P = 0.5 secs, N = 8, ⇒ T = 0.5*8! = 20.160 secs. Any value above T is 'suspicious' time.
My question is, how can one introduce a probability function which asymptotically reaches 1, while running time increases infinitely?
Our 'evaluation' shall depend on a constant time P, the size N of our input, and the time complexity Q of our current problem, thus it may have this form: f(P, N, Q) = ... , whereas 0 ≤ f ≤ 1, f increasing, and f indicates the probability of having 'fallen' in a non-terminating state.
If this approach isnt enough, how can we make sure that after a certain amount of time, our program is probably running endlessly?

Find modulo of large number with large number

I have a number n and m. They are both very large and exceed the limits of a C++ long long. How do i find n mod m accurately?
Naive n % m only works up to 2^63-1, getting 9 on the online judge.
Adding one digit of n at a time and using % m works for small m, but is quite slow, and without hardcoding for the special case where m = 1, it exceeds the time limit on such a small m. It gets 37 on the online judge.
So is there a method of calculating n mod m given them as strings?
Problem: https://dunjudge.me/analysis/problems/669/
Given that m is constrained to be less than 10! (which is 3628800) you can process the digits of n one at a time in an easy way.
If the digits of n are d[i] where i goes from 0 to N-1 (with d[0] being the most significant digit), then something like this works (pseudocode):
R = 0
for i = 0 to N-1
R = (10 * R + d[i]) % m
return R
One way to handle this is the binary approach. Algorithm steps would go like this:
Set a = n shift a to left as much as possible while still m > a
m = m - a
If m < n DONE result is in m, Else go to step 1
For first step, since you have both numbers in strings, finding the index of the first 1from left for both m and n and taking their difference would give the necessary number of shifts.
I haven't implemented it, however all operations are basic binary ops (avoids relatively costly modulo) and algorithm's complexity is O(N) where N is the number of digits; so it should have a nice performance.

Number of addition and multiplication operators in this algorithm

Consider the following algorithm:
i := 1
t := 0
while i ≤ n
t := t + i
i := 2i
I'm interested in finding out how many addition and multiplication operations this algorithm executes; however, I'm running into trouble. I understand that the value of i doubles after each iteration, but I don't know how to generalize the algorithm to give a correct number of operations up until the value of n. If anyone can shed some light on the issue, I'd greatly appreciate it.
Thank you!
Since the value of i doubles every loop and i <= n
i*2^x <= n
and maximizing x gives the number of loops. Since i = 1
2^x = n
x = floor log(n)
and we perform 1 addition and 1 multiplication per loop. I think you can take it from here :)

Programing Pearls - Random Select algorithm

Page 120 of Programming Pearls 1st edition presents this algorithm for selecting M equally probable random elements out of a population of N integers.
InitToEmpty
Size := 0
While Size < M do
T := RandInt(1,N)
if not Member(T)
Insert(T)
Size := Size + 1
It is stated that the expected number of Member tests is less than 2M, as long as M < N/2.
I'd like to know how to prove it, but my algorithm analysis background is failing me.
I understand that the closer M is to N, the longer the program will take, because the result set will have more elements and the likelihood of RandInt selecting an existing one will increase proportionally.
Can you help me figuring out this proof?
I am not a math wizard, but I will give it a rough shot. This is NOT guaranteed to be right though.
For each additional member of M, you pick a number, see if it's there, and if is add it. Otherwise, you try again. Trying something until you're successful is called a geometric probability distribution.
http://en.wikipedia.org/wiki/Geometric_distribution
So you are running M geometric trials. Each trial has expected value 1/p, so will take expected 1/p tries to get a number not already in M. p is N minus the number of numbers we've already added from M divided by N (i.e. how many unpicked items / total items). So for the fourth number, p = (N -3) / N, which is the probability of picking an unused number, so the expected number of picks for the third number is N / N-3 .
The expected value of the run time is all of these added together. So something like
E(run time) = N/N + N/(N -1) + N/(N -2 ) ... + N/ (N-M)
Now if M < N/2, then the last element in that summation is bounded above by 2. ((N/N/2) == 2)). It's also obviously the largest element in the whole summation. So if the biggest element is two picks, and there are M elements being summed, the EV of the whole run time is bounded above by 2M.
Ask me if any of this is unclear. Correct me if any of this is wrong :)
Say we have chosen K elements out of N. Then our next try has probability (N-K)/N of succeeding, so the number of tries that it takes to find the K + 1 st element is geometrically distributed with mean N/(N-K).
So if 2M < N we expect it to take less than two tries to get each element.

Resources