简体   繁体   中英

How do I calculate Time Complexity for this particular algorithm?

I know there are many other questions out there asking for the general guide of how to calculate the time complexity, such as this one .

From them I have learnt that when there is a loop, such as the (for... if...) in my Python programme, the Time complexity is N * N where N is the size of input. (please correct me if this is also wrong) (Edited once after being corrected by an answer)

# greatest common divisor of two integers 

a, b = map(int, input().split())
list = []

for i in range(1, a+b+1):
  if a % i == 0 and b % i == 0:
    list.append(i) 

n = len(list)
print(list[n-1])

However, do other parts of the code also contribute to the time complexity, that will make it more than a simple O(n) = N^2? For example, in the second loop where I was finding the common divisors of both a and b (a%i = 0), is there a way to know how many machine instructions the computer will execute in finding all the divisors, and the consequent time complexity, in this specific loop?

I wish the question is making sense, apologise if it is not clear enough.

Thanks for answering

First, a few hints:

  1. In your code there is no nested loop. The if -statement does not constitute a loop.
  2. Not all nested loops have quadratic time complexity.
  3. Writing O(n) = N*N doesn't make any sense: what is n and what is N ? Why does n appear on the left but N is on the right? You should expect your time complexity function to be dependent on the input of your algorithm, so first define what the relevant inputs are and what names you give them.
  4. Also, O(n) is a set of functions (namely those asymptotically bounded from above by the function f(n) = n , whereas f(N) = N*N is one function. By abuse of notation, we conventionally write n*n = O(n) to mean n*n ∈ O(n) (which is a mathematically false statement), but switching the sides ( O(n) = n*n ) is undefined. A mathematically correct statement would be n = O(n*n) .
  5. You can assume all (fixed bit-length) arithmetic operations to be O(1), since there is a constant upper bound to the number of processor instructions needed. The exact number of processor instructions is irrelevant for the analysis.

Let's look at the code in more detail and annotate it:

a, b = map(int, input().split()) # O(1)
list = []                        # O(1)

for i in range(1, a+b+1):        # O(a+b) multiplied by what's inside the loop
  if a % i == 0 and b % i == 0:  # O(1)
    list.append(i)               # O(1) (amortized)

n = len(list)                    # O(1)
print(list[n-1])                 # O(log(a+b))

So what's the overall complexity? The dominating part is indeed the loop (the stuff before and after is negligible, complexity-wise), so it's O(a+b) , if you take a and b to be the input parameters. (If you instead wanted to take the length N of your input input() as the input parameter, it would be O(2^N) , since a+b grows exponentially with respect to N .)

One thing to keep in mind, and you have the right idea, is that higher degree take precedence. So you can have a step that's constant O(1) but happens n times O(N) then it will be O(1) * O(N) = O(N).

Your program is O(N) because the only thing really affecting the time complexity is the loop, and as you know a simple loop like that is O(N) because it increases linearly as n increases.

Now if you had a nested loop that had both loops increasing as n increased, then it would be O(n^2).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM