time complexity when while not execute - big-o

What is the “best case” time complexity of the following segment of program?
n=0
sum=0
input(x)
while x!=-999 do
n=n+1
sum=sum+x
input(x)
end {while}
mean=sum/n
Does "best case" could be O(1) when user in the first time type “-999”
note: when user type -999 in first time, "mean" will be 0/0, result of function is undefined

The worst case is infinity,which means this program never stops. I would not even call it an algorithm, as some definitions of "algorithm" require a finite set of inputs, while other require that it terminates before a given number of calculation steps.
Which means O() is not applicable here.

Algorithm's complexity is usually defined in relation to some kind of data. It can be the input data, as in your case.
Imagine for a while, that the data is not inputted manually, but provided in an array in the app. What would the complexity be then?
In this case the amount of numbers processed is N, and the loop runs once for each N, so you can assume that the complexity is O(N).

Related

Determine running time for multiple calls of a functions

Assume I have a function f(K) that runs in amortised logarithmic time in K, but linear worst case time. What is the running time of:
for i in range(N): f(N) (Choose the smallest correct estimate)
A. Linearithmic in N
B. Amortised linear in N
C. Quadratic in N
D.Impossible to say from the information given
Let's say f(N) just prints "Hello World" so it doesn't depend on how big the parameter is. Can we say the total running time is amortised linear in N ?
This kinda looks like a test question, so instead of just saying the answer, allow me to explain what each of these algorithmic complexity concepts mean.
Let's start with a claim function f(n) runs in constant time. I am aware it's not even mentioned in the question, but it's really the basis for understanding all other algorithmic complexities. If some function runs in constant time, it means that its runtime is not dependent on its input parameters. Note that it could be as simple as print Hello World or return n, or as complex as finding the first 1,000,000,000 prime numbers (which obviously takes a while, but takes the same amount of time on every invocation). However, this last example is more of an abuse of the mathematical notation; usually constant-time functions are fast.
Now, what does it mean if a function f(n) runs in amortized constant time? It means that if you call the function once, there is no guarantee on how fast it will finish; but if you call it n times, the sum of time spent will be O(n) (and thus, each invocation on average took O(1)). Here is a lengthier explanation from another StackOverflow answer. I can't think of any extremely simple functions that run in amortized constant time (but not constant time), but here is one non-trivial example:
called = 0
next_heavy = 1
def f(n):
called += 1
if called == next_heavy:
for i in range(n):
print i
next_heavy *= 2
On 512-th call, this function would print 512 numbers; however, before that it only printed a total of 511, so it's total number of prints is 2*n-1, which is O(n). (Why 511? Because sum of powers of two from 1 to 2^k equals 2^(k+1).)
Note that every constant time function is also an amortized constant time function, because it takes O(n) time for n calls. So non-amortized complexity is a bit stricter than amortized complexity.
Now your question mentions a function with amortized logarithmic time, which similarly to above means that after n calls to this function, the total runtime is O(nlogn) (and average runtime per one call is O(logn)). And then, per question, this function is called in a loop from 1 to N, and we just said that by definition those N calls together would run in O(NlogN). This is linearithmic.
As for the second part of your question, can you deduce what's the total running time of the loop based on our previous observations?

Is an iterative solution for Fibonacci series pseudo-polynomial?

So when we do an iterative solution to find the nth number in a Fibonacci sequence, we run a for loop (n-2) times. This would mean that the time complexity would be O(n). Is this correct or would it actually be pseudo-polynomial depending on the number of bits of the input, much like the Knapsack problem?
Here, I assume Fib(n) is an iterative version of a program that computes Fibonacci numbers. Perhaps something like:
def Fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
return a
"Fib(n) is pseudo-polynomial" means in this context that computing Fib is bounded by a polynomial of its argument, n, but isn't bounded by a polynomial function of the size of the argument, log(n). That's true in this case.
"Fib(n) is O(n)" is a statement about the running time of Fib with respect to the value of its argument. There's sometimes ambiguity what "n" is, but here there's none -- it's the input to Fib, otherwise "n" would refer to two different things in the original statement. That's true here (although see the technical side-note below).
"Fib is O(n)" is ambiguous. There are people who will tell you that n clearly refers to the argument, and there's others who will tell you that n always refers to the size of the argument. The truth is that it's ambiguous and if it's not clear in context you should say what you mean (or ask what it means if you hear it and are confused). One context where it's not ambiguous is when you're talking about classes of P/NP problems -- there it's assumed that complexities are always relative to the size of the input.
A technical side-note
The iterative version of Fib(n) performs O(n) arithmetic operations, but whether it's O(n) time depends on your computational model, and specifically whether it can perform arbitrary integer arithmetic operations in O(1) time. Personally, I'd be careful and say "Fib(n) performs O(n) arithmetic operations" rather than "Fib(n) is O(n)" -- and if you plot the running time of Fib(n), you'll find it's not linear time in practice, as real bignum implementations are certainly not O(1) for all basic operations.
Yes, it is infact O(n). The time complexity of Knapsack Problem is a really weird one and is an exception.

Does a simple for loop have exponential complexity?

The time complexity of an algorithm is defined as the amount of time taken by it to run as a function of the length of the input.
If I have a simple for loop function in C, which runs for a given input n then:
the length of n is log n(number of bits required to represent it).
Since input is log n and the loop runs n times, the code runs exponentially many times in it's input length ( 2^(log n) = n))
C code:
int forfunction(unsigned int n){
unsigned int i=0;
for(;i<n;i++){
// do something ordinary
}
return 0;
}
This for loop being an example.
But we will never hear anyone say, that such a for loop program is exponential in it's input (the bits required to store n). Why is it so? The only difference I see is that this is a program and time complexity is defined for an algorithm. But even if it is, then why does this not have an impact/taken into account when we want to do a rough time complexity of a program?
EDIT:
Further clarification: I find it reasonable to claim it is exponential in it's input ( might be wrong =) ). If it so, then if a simple for loop is exponential, then what about other hard problems? Clearly this for loop is not a worry for anyone today. Why is it not? Why does this not have (much) real world implications when compared to other hard problems(EXP,NP-Hard,etc...)? Note: I am using hard the way it used to define NP-Hard problems.
Elaborating on #Anonymous's answer: The question you should be asking is "exponential in what?" Ultimately, whether this is exponential time depends on how n is presented to you.
If n is given to you as an explicit binary integer using O(log n) bits, then this function will run in pseudopolynomial time (technically exponential in the number of input bits, but polynomial in the numeric value of the input). This is why simple primality testing algorithms like trial division (divide n by all numbers from 2 up to √n and see if any of them are factors) technically run in exponential time even though they do run in time O(√n).
On the other hand, if n is given to you implicitly using O(n) bits (perhaps as the number of nodes in a graph given an adjacency matrix, or perhaps as the number of characters in a string given a string), then the runtime is polynomial because the input has at least linear size and linear work is done. This is why algorithms like DFS or BFS, which have runtimes of the form O(m + n), run in polynomial time: the number of bits in the input is Ω(m + n).
Hope this helps!
The amount of time a function takes is a function parameterised by something. Often it'll be the size of the input, but other times it's an explicit parameter, and it's up to you, when you're describing a function, to make it clear what you mean. Because it's often "obvious" what the parameterisation is from context, it's often omitted which leads to a lot of confusion when the parameterisation is not obvious to everyone.
When you add the word "complexity" then all that means is that instead of describing a function, you're saying it belongs to a particular class of functions. It doesn't obviate the need to say what the function is and what its argument is.
Techincally speaking the for loop or for that matter all linear programs are exponential in their inputs but this is not used to explain their runtime because for the simple reason that runtime is defined how it varies with change in input . Here in these problems it is considered the no of input bits is constant for example you might define the algorithm for only integer input so its input has always 32 bits so it is considered constant as even if value of n changes no of bits dont so constant terms cannot be used to define growth of algorithm hence omitted.

Complexity of Operation That Isn't Performed

If I want to describe the time complexity of an operation that isn't performed in some program, how could I do this? For example, given the following trivial function:
def trivial():
return
How could I describe the upper bound on the time consumed by calling Sort? Could I say that the time required by calling Sort is O(0)? This seems to be true given the definition of O-notation.
if some program run for finite no of statements then its complexity is of order 1.
complexity is calculated for cases where input size defines the no. of statements executed.
if no of input are n then, complexity is of order n if it runs for n times.
if no of input are n then, complexity is of order n^2 if it runs for n*n times, and so on.
if no. of times function executed doesn't depends on input size (or it don't take any input)
then its of order 1, no matter how long that function is.

Program/algorithm to find the time complexity of any given program

I like to know whether it is possible to "write a program or algorithm" to find the time complexity of any given program taken as input.
Input : any program (P) [in any language or of a particular language]
Output : time complexity of that program (P).
Have there been any prior attempts to write such a program?
Are there any algorithms available for this purpose?
If so please provide the necessary links, references or with any kind of guidance possible.
No. It's not possible. This is a form of the halting problem.
Proving the complexity of an arbitrary algorithm is not possible but in principle you could estimate it:
choose n, the size of the input
run the algorithm
observe t(n), the time needed to run the algorithm for input of size n
choose another n, repeat steps 2 and 3 until you have a lot of data
regress t(n) on n, n^k, log(n), n log(n), n!, or any other
term that might be appropriate
choose a term with statistical significance and declare that
to be your estimated complexity of the algorithm
There are any number of pitfalls to this approach
This will not prove anything, only estimate
If t(n) gets really large for large n, it will take a long time to
collect enough data for your analysis
There are many ways that this approach can be fooled unless you use huge values
of n. For example, this algorithm will look like O(1) unless you use astronomical
values for n
sleep for 10 days
run an O(n log(n)) sorting algorithm
And other SO users can come up with many more. But in some cases, like when you do a complexity analysis of an algorithm and want to verify it empirically, this is still a useful approach.
can't we introduce some more variables in the algorithm itself and find the complexity the same way we do it manually.
like for example we can have a variable in an insertion sort say n=0 which keeps the track of the entire looping part of the algorithm and then give the answer as O(n^2)
Well I think you do this by assuming all cases.
1:Like first make a module which can extract each of the instruction
2: Do make a database of instruction to match up with the program instruction.
3: calculate the complexity by fetching the appropriate time complexity set by you in database and that's all.

Resources