In short, the worst-case run-times are:
Version 1: O(n)
Version 2: O(n^2)
Version 3: O(n)
A more detailed analysis...
For this algorithm you will have to consider best-case, worst-case and average-case runtimes to get a meaningful comparison.
For each of them, the following should exemplify these:
bestCase = [ true, true, ...] // the first two are true
worstCase = [ false, false, ..., false] // all are false
averageCase = [ true, ..., true, ..., false // second true value is found about half-way
For all of your algorithms, the best-case run-time is O(2)
, meaning constant-time.
In the worst-case, your first algorithm is O(n)
, meaning linear run-time.
However, in the worst-case your second algorithm will degenerate very specifically, since at each step you have one fewer element to check against. You end up with the summation n + (n-1) + (n-2) + ...
, which will evaluate to n(n-1)/2
which, as you rightly said, is in O(n^2)
, and grows quadratically.
In the 'worst-case' where all are false (as we will see, this isn't in fact the worst-case for version 3), your third algorithm actually runs in linear time, since the if
statement prevents the second loop from running.
As it turns out, version 3 will never run in quadratic time: it would be linear in the average and worst case, since it scans linearly for the first true
, then scans the rest linearly for the second true
only after finding that, although it doesn't even work!
Because you have two returns in your inner for-loop, once the first true
value has been encountered, it will return true
if the next immediate neighbor is true
. However, if the next immediate neighbor is false
, it immediately returns false
and doesn't check any of the other values. This means that on the input:
[ true, false, true ]
version 3 would return false as soon as it saw the second false value. (Technically I am assuming here that you want this return false
to be executed inside of the for loop, in which case you also need to add { }
, and likewise with your first version. While not always necessary, it helps clarify what exactly is happening, especially since this doesn't match your indentation currently. When absent only the statement immediately following is included on the loop/if body.) I suspect that, even if implemented correctly, *version 3 will still have a worse-case run time which is linear, on the input:
[true, false, false, ..., false]
The first true would cause it to scan n
times in the inner loop, but then the outer loop would just continue running up to n without running the inner loop again, giving you a total of 2n-1 operations, which of course is in O(n)
.
If your { }
are correct and it is simply your indentation which is wrong, then these analyses may need to be modified slightly, but this is the kind of thinking which you need to apply to big-O problems (and asymptotic analysis in general).