18

Let's say we have an array of 1.000.000 elements and we go through all of them to check something simple, for example if the first character is "A". From my (very little) understanding, the complexity will be O(n) and it will take some X amount of time. If I add another IF (not else if) to check, let's say, if the last character is "G", how will it change complexity? Will it double the complexity and time? Like O(2n) and 2X?

I would like to avoid taking into consideration the number of calculations different commands have to make. For example, I understand that Len() requires more calculations to give us the result than a simple char comparison does, but let's say that the commands used in the IFs will have (almost) the same amount of complexity.

Evripidis Bourlas
  • 183
  • 1
  • 1
  • 4
  • I’m voting to close this question because it is not about the practice of developing software, but about theory. Theory has its own Stack Exchange site, at [cs.se]. – Charles Duffy Dec 22 '21 at 16:52

4 Answers4

21

O(2n) = O(n). Generalizing, O(kn) = O(n), with k being a constant. Sure, with two IFs it might take twice the time, but execution time will still be a linear function of input size.

Edit: Here and Here are explanations, with examples, of the big-O notation which is not too mathematic-oriented

dario_ramos
  • 7,118
  • 9
  • 61
  • 108
6

Asymptotic complexity (which is what big-O uses) is not dependent on constant factors, more specifically, you can add / remove any constant factor to / from the function and it will remain equivalent (i.e. O(2n) = O(n)).

Assuming an if-statement takes a constant amount of time, it will only add a constant factor to the complexity.

A "constant amount of time" means:

  • The time taken for that if-statement for a given element is not dependent on how many other elements there are in the array
  • So basically if it doesn't call a function which looks through the other elements in the array in some way or something similar to this
  • Any non-function-calling if-statement is probably fine (unless it contains a statement that goes through the array, which some language allows)

Thus 2 (constant-time) if-statements called for each each element will be O(2n), but this is equal to O(n) (well, it might not really be 2n, more on that in the additional note).

See Wikipedia for more details and a more formal definition.

Note: Apart from not being dependent on constant factors, it is also not dependent on asymptotically smaller terms (terms which remain smaller regardless of how big n gets), e.g. O(n) = O(n + sqrt(n)). And big-O is just an upper bound, so saying it is O(n9999) would also be correct (though saying that in a test / exam will probably get you 0 marks).

Additional note: The problem when not ignoring constant factors is - what classifies as a unit of work? There is no standard definition here. One way is to use the operation that takes the longest, but determining this may not always be straight-forward, nor would it always be particularly accurate, nor would you be able to generically compare complexities of different algorithms.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
1

Some key points about time complexity:

  1. Theta notation - Exact bound, hence if a piece of code which we are analyzing contains conditional if/else and either part has some more code which grows based on input size then exact bound can't be obtained since either of branch might be taken and Theta notation is not advisable for such cases. On the other hand, if both of the branches resolve to constant time code, then Theta notation can be applicable in such case.
  2. Big O notation - Upper bound, so if a code has conditionals where either of the conditional branches might grow with input size n, then we assume max or upper bound to calculate the time consumption by the code, hence we use Big O for such conditionals assuming we take the path that has max time consumption. So, the path which has lower time can be assumed as O(1) in amortized analysis(including the fact that we assume this path has no no recursions that may grow with the input size) and calculate time complexity Big O for the lengthiest path.
  3. Big Omega notation - Lower bound, This is the minimum guaranteed time that a piece of code can take irrespective of the input. Useful for cases where the time taken by code doesn't grow based on input size n, but it consumes a significant amount of time k. In these cases, we can use the lower bound analysis.

Note: All of these notations doesn't depend upon the input being best/avg/worst and all of these can be applied to any piece of code.

So as discussed above, Big O doesn't care about the constant factors such as k and only sees how time increases with respect to growth in n, in which case here it is O(kn) = O(n) linear.

PS: This post was about the relation of big O and conditionals evaluation criteria for amortized analysis.

mahee96
  • 705
  • 6
  • 15
-2

It's related to a question I posted myself today.

In your example it depends on whether you can jump from the first to the last element and if you can't then it also depends on the average length of each entry.

If as you went down through the array you had to read each full entry in order to evaluate your two if statements then your order would be O(1,000,000xN) where N is the average length of each entry. IF N is variable then it will affect the order. An example would be standard multiplication where we perform Log(N) additions of an entry which is Log(N) in lenght and so the order is O(Log^2(N)) or if you prefer O((Log(N))^2).

On the other hand if you can just check the first and last character then N = 2 and is constant so can be ignored.

This is an IMPORTANT point you have to be careful though because how can you decide if your multipler can be ignored. For example say we were doing Log(N) additions of a Log(N/100) number. Now just because Log(N/100) is the smaller term doesn't mean we can ignore it. The multiplying factor cannot be ignored if it is variable.

Rhuaidhri Tynan
  • 121
  • 1
  • 1
  • 8
  • 1
    -1 Constant factors have no effect on the complexity. They may influence the actual observed runtime performance (and severely so), but that is a different thing. – ComicSansMS Jun 04 '13 at 13:34
  • As I tried to make clear it depends on what your reading as a constant factor. For example if your doing N iterations and your "constant" factor is N then you CANNOT just disregard that N as a constant. If that was the case multiplication would be a Log(N) operation not a Log(N^2) one. The constant as I say HAS to be small compared to your number of iterations. I should add that in this case N isn't a constant since it depends as I said on the average size of the array elements which is another variable. You can set a fixed upper limit on it which is what your doing with worst case anyway – Rhuaidhri Tynan Jun 04 '13 at 14:43
  • I think we are cross posting. You missed my edit? N is another variable it's not a constant and I didn't call it one in my original post I only did here because that's how you referred to it. Let's call it the multipler. The point is the multipler can only be ignored if it small compared to what it is multiplying. Oops scrap that I see I did call it a constant at the end. Wasn't what I meant. I mean multiplier but when I edited and added that final note I made a mistake. – Rhuaidhri Tynan Jun 04 '13 at 14:51
  • I think I see what you mean now, but your wording is still incorrect. If N is a constant it can be ignored for complexity, no matter how big it is. If N is not a constant but depends on the size of the input it can not be ignored. This is true even if the term is small compared to the main term of the complexity. Even a log(N) term grows towards infinity for large N, so you must not ignore it! Small and large are the wrong categories here. It's about constant or non-constant. – ComicSansMS Jun 04 '13 at 15:20
  • Yea I see what you mean about wrong wording it should say as long as the multiplying factor is variable it cannot be ignored although I worry that confuses people too because we can ignore a small variables when they do not impact the significant complexity such as if we we adding another variable which we know will be relatively small. Eg O(Log(N^2) + Log(N)) = O(Log(N^2)). – Rhuaidhri Tynan Jun 04 '13 at 15:33
  • Thanks. A typo I've made multiple times should be Log^2(N) = (Log(N))^2. – Rhuaidhri Tynan Jun 04 '13 at 16:07