Time complexity of this for loop - time-complexity

Could anyone explain me the time complexity of this method?
int sqrt = (int) Math.sqrt(n) + 1;
for (int i = 2; i < sqrt; i++) {
if (n % i == 0) {
return false;
}
}
return true;
I'm not really good in this subject and tried to find out some info online but could't find any explanation.

its On(1) - linear, as it its linearly proportional on i (or less due to early stopping from module check); this is typical for a one level for loop

Related

Finding the time complexity of a recursive algorithm with a double for loop

I am trying to find the tightest upper bound for the following upper bound. However, I am not able to get the correct answer. The algorithm is as follows:
public staticintrecursiveloopy(int n){
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.println("Hello.");
}
} if(n <= 2) {
return 1;
} else if(n % 2 == 0) {
return(staticintrecursiveloopy(n+1));
} else{
return(staticintrecursiveloopy(n-2));
}
}
I tried to draw out the recursion tree for this. I know that for each run of the algorithm the time complexity will be O(n2) plus the time taken for each of the recursive calls. Also, the recursion tree will have n levels. I then calculated the total time taken for each level:
For the first level, the time taken will be n2. For the second level, since there are two recursive calls, the time taken will be 2n2. For the third level, the time taken will be 4n 2 and so on until n becomes <= 2.
Thus, the time complexity should be n2 * (1 + 2 + 4 + .... + 2n). 1 + 2 + 4 + .... + 2n is a geometric sequence and its sum is equal to 2n - 1.Thus, the total time complexity should be O(2nn2). However, the answer says O(n3). What am I doing wrong?
Consider the below fragment
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.println("Hello.");
}
}
This doesn't need any introduction and is O(n2)
Now consider the below fragment
if(n <= 2) {
return 1;
} else if(n % 2 == 0) {
return(staticintrecursiveloopy(n+1));
} else {
return(staticintrecursiveloopy(n-2));
}
How many times do you think this fragment will be executed?
If n%2 == 0 then the method staticintrecursiveloopy will be executed 1 extra time. Otherwise it goes about decresing it by 2, thus it'll be executed n/2 times (or (n+1)/2 if you include the other condition).
Thus the total number of times the method staticintrecursiveloopy will be executed is roughly n/2 which when expressed in terms of complexity becomes O(n).
And the method staticintrecursiveloopy calls a part with complexity O(n2) in each iteration, thus the total time complexity becomes
O(n) * O(n2) = O(n3).

Am i calculating the big-o correctly?

Following loops:
for(var i = 0; i < A; i++) {
for(var j = 0; j < B; j++) {
for(var k = 0; k < C; k++) {
//not concerned with instructions here
}
}
}
As I understand each loop complexity is 2n+2 so based on that I calculate the complexity of above nested loops to be (2A+2)*((2B+2)*(2C+2)). Is this correct? if so, how do I get the big-o out of it?
Edit 1
I've learned so much about big-o since this question was asked and have found an interesting visualization that I'd like to place here in case others come across this thread. For detailed reference (way better than student textbooks) and original drawing check out Wikipedia. There are a variety of time complexities explained there.
Since the original question involves three nested loops each with a different n, then the big-o is O(A * B * C) as mentioned in the answers. The difficulty arises when we try to determine the big-o for something like this where A is an array of objects (aka hash in some languages). The algorithm itself non-sense and is for demonstration only (although I've been asked non-sense in interviews before):
var cache = {}
for(var i = 0; i < A.length; i++) {
var obj = A[i]
if(!obj.someProperty) {
continue;
}
else if(cache[obj.someProperty]) {
return obj;
}
else if(obj.someProperty === 'some value') {
for(var j = 1; j < A.length; j++) {
if(A[j].someProperty === obj.someProperty) {
cache[obj.someProperty] = obj.someProperty
break
}
}
}
else {
for(var j = i; j < A.length; j++) {
//do something linear here
}
}
}
The outer loop is O(A.length). For inner loops:
obj.someProperty does not exist, we have no complexity per theory.
obj.someProperty is in the cache, we have no complexity per theory.
obj.someProperty is equal to some value either of:
we have O(A.length - 1) where there are no duplicates
We have O(A.length - x) where A.length - x refers to a duplicate's index within A.
Everything else, we have O(log A.length)
At best performance this algorithm gives us O(3) when A[0] and A[1] are considered duplicates and A[0].someProperty === 'some value' as we'll have one iteration for outer loop and one iteration of inner loop (3.2 A.length - x = index 1, finally 3rd iteration returns cached value breaking out of the outer loop entirely. At worse we'll have O(A.length log A.length) as the outer loop and inner loop at 4 are exhausted when no object has someProperty === 'some value'.
To "optimize" this algorithm we can simply write as follows:
for(var i = 0; i < A.length; i++) {
if(A[i].someProperty === 'some value') {
return obj
}
else {
for(var j = i; j < A.length; j++) {
//do something linear here
}
}
}
The outermost for-loop runs a total of A times. For each iteration, the second-level for-loop runs B times, each time triggering C iterations of the omitted instructions.
Thus, the time complexity is O(A * B * C).
Constants are ignored while calculating the time complexity
O((2A+2)*((2B+2)*(2C+2)))
=> O((2A)(2B)(2C))
=> O(8*ABC)
=> O(ABC)

How to proof the time complexity of this Fibonacci sequence is O(n)

In the following code, i know that the time complexity is O(n) but how do i proof it in a proper way?
Is saying that searching array is O(n) enough?
int f[N];
F(n)
{
if (f[n] >= 0) return f[n];
f[n] = F(n-1) + F(n-2);
return f[n];
}
int main()
{
read n;
f[0] = 0; f[1] = 1;
for (i = 2; i <= n; i++)
f[i] = -1;
print F(n);
}
For each element of the array you call F. it may seem as a recursion to you but a bad implementation. each of the f[n-1] and f[n-2] calls actually just returns the values.
You will have 3n call to F(n), so still O(n).
If you are not obligated to recursion, you can program it with a single loop.

how much time will fibonacci series will take to compute?

i have created the recursive call tree by applying brute force technique but when i give this algorithm 100 values it takes trillion of years to compute..
what you guys suggest me to do that it runs fast by giving 100 values
here is what i have done so far
function fib(n) {
if (n =< 1) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
You can do it also with a loop:
int a = 1;
int b = 1;
for(int i = 2; i < 100; i++){
int temp = a + b;
a = b;
b = temp;
}
System.out.println("Fib 100 is: "+b);
The runtime is linear and avoids the overhead caused by the recursive calls.
EDIT: Please note that the result is wrong. Since Fib(100) is bigger than Integer.MAX_VALUE you have to use BigInteger or similar to get the correct output but the "logic" will stay the same.
You could have a "cache", where you save already computed Fibonacci numbers. Every time you try to compute
fib(n-1) /* or */ fib(n-2) ;
You would first look into your array of already computed numbers. If it's there, you save a whole lot of time.
So every time you do compute a fibonacci number, save it into your array or list, at the corresponding index.
function fib(n)
{
if (n =< 1)
{
return n;
}
if(fiboList[n] != defaultValue)
{
return fiboList[n];
}
else
{
int fibo = fib(n-1) + fib(n-2);
fiboList[n] = fibo;
return fibo;
}
}
You can also do it by dynamic programming:
def fibo(n):
dp = [0,1] + ([0]*n)
def dpfib(n):
return dp[n-1] + dp[n-2]
for i in range(2,n+2):
dp[i] = dpfib(i)
return dp[n]

Comparing time complexities

Let's say we have an algorithm that goes through a list of n numbers twice and counts the number of the ones above 50 in one run and the ones below 50 in the other run and stores these in two variables.
If we change it to do the same in one run by incrementing not just one but either of the variables in each step, do we change time complexity of the algorithm? Do we consider the new one faster?
I know it will require less steps but not exactly sure about time complexity notation.
EDIT:
Pseudocode 1:
for (i = 0; i < TOTAL_NUMBERS; i++) {
if (numbers[i] >= 50) {
greaterThan50++;
}
}
for (i = 0; i < TOTAL_NUMBERS; i++) {
if (numbers[i] < 50) {
lessThan50++;
}
}
Pseudocode 2:
for (i = 0; i < TOTAL_NUMBERS; i++) {
if (numbers[i] >= 50) {
greaterThan50++;
}
else {
lessThan50++;
}
}
Something is simple if you can obtain the same result but with smallest expression posible. So in this case if you combine the update of the two counters in the same loop the algorithm will need less CPU cycles to be executed. You can also save time in the number validation cause you can just make one if / else statement to do what you need.
A pseudocode could look like this:
for (i = 0; i < TOTAL_NUMBERS; i++) {
if (numbers[i] >= 50) {
greaterThan50 ++;
}
else {
lessThan50 ++;
}
}
If you want to exclude the numbers that are equal 50 you can do something like:
for (int i = 0; i < TOTAL_NUMBERS; i++) {
if (numbers[i] > 50) {
greaterThan50 ++;
}
else if (numbers[i] < 50) {
lessThan50 ++;
}
}
As you might notice in this last example you are doing an extra validation so it will take an extra step, but this algorithm will still be much faster than looping through the list twice (and also simpler since it requires less lines of code and makes the code more readable and easy to understand).
I hope this helps with your question :)
Big O notation is a general statement for how a measurement (execution time in your case) changes as input grows. The first takes twice as long to execute, but both versions execution times grow linearly with regard to input size, so they're both O(n) algorithms.
more reading here: http://en.wikipedia.org/wiki/Big_O_notation