Asymptotic analysis - algorithm

I'm having trouble understanding how to make this into a formula.
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j += i) {
I realize what happens, for every i++ you have 1 level of multiplication less of j.
i = 1, you get j = 1, 2, 3, ..., 100
i = 2, you get j = 1, 3, 5, ..., 100
I'm not sure how to think this in terms of Big-theta.
The total of j is N, N/2, N/3, N/4..., N/N (My conclusion)
How would be best to try and think this as a function of N?

So your question can be actually reduced to "What is the tight bound for the harmonic series 1/1 + 1/2 + 1/3 + ... + 1/N?" For which the answer is log N (you can consider it as continuous sum instead of discrete, and notice that the integral of 1/N is log N)
Your harmonic series is the formula of the whole algorithm (as you have correctly concluded)
So, your sum:
N + N/2 + N/3 + ... + N/N = N * (1 + 1/2 + 1/3 + ... + 1/N) = Theta(N * log N)
So the tight bound for the algorithm is N*log N
See the [rigorous] mathematical proof here (see the "Integral Test" and "Rate of Divergence" part)

Well, you can methodically use Sigma notation:

Related

How to find the big theta?

Here's some code segment I'm trying to find the big-theta for:
i = 1
while i ≤ n do #loops Θ(n) times
A[i] = i
i = i + 1
for j ← 1 to n do #loops Θ(n) times
i = j
while i ≤ n do #loops n times at worst when j = 1, 1 times at best given j = n.
A[i] = i
i = i + j
So given the inner while loop will be a summation of 1 to n, the big theta is Θ(n2. So does that mean the big theta is Θ(n2) for the entire code?
The first while loop and the inner while loop should be equal to Θ(n) + Θ(n2) which should just equal Θ(n2).
Thanks!
for j = 1 to n step 1
for i = j to n step j
# constant time op
The double loop is O(n⋅log(n)) because the number of iterations in the inner loop falls inversely to j. Counting the total number of iterations gives:
floor(n/1) + floor(n/2) + ... + floor(n/n) <= n⋅(1/1 + 1/2 + ... + 1/n) ∼ n⋅log(n)
The partial sums of the harmonic series have logarithmic behavior asymptotically, so the above shows that the double loop is O(n⋅log(n)). That can be strengthened to Θ(n⋅log(n)) with a math argument involving the Dirichlet Divisor Problem.
[ EDIT ] For an alternative derivation of the lower bound that establishes the Θ(n⋅log(n)) asymptote, it is enough to use the < part of the x - 1 < floor(x) <= x inequality, avoiding the more elaborate math (linked above) that gives the exact expression.
floor(n/1) + floor(n/2) + ... + floor(n/n) > (n/1 - 1) + (n/2 - 1) + ... + (n/n - 1)
= n⋅(1/1 + 1/2 + ... + 1/n) - n
∼ n⋅log(n) - n
∼ n⋅log(n)

What's the complexity of sum i=0 -> n (n_i*i))

This is a test I failed because I thought this complexity would be O(n), but it appears i'm wrong and it's O(n^2). Why not O(n)?
First, notice that the question does not ask what is the time complexity of a function calculating f(n), but rather the complexity of the function f(n) itself. you can think about f(n) as being the time complexity of some other algorithm if you are more comfortable talking about time complexity.
This is indeed O(n^2), when the sequence a_i is bounded by a constant and each a_i is at least 1.
By the assumption, for all i, a_i <= c for some constant c.
Hence, a_1*1+...+a_n*n <= c * (1 + 2 + ... + n). Now we need to show that 1 + 2 +... + n = O(n^2) to complete the proof.
1 + 2 + ... + n <= n + n + ... + n = n * n = n ^ 2
and
1 + 2 + ... + n >= n / 2 + (n / 2 + 1) + ... + n >= (n / 2) * (n / 2) = n^2/4
So the complexity is actually Theta(n^2).
Note that if a_i was not constant, e.g., a_i = i then the result is not correct.
in that case, f(n) = 1^2 + 2^2 + ... + n^2 and you can show easily (using the same method as before) that f(n) = Omega(n^3), which means it's not O(n^2).
Preface, not super great with complexity-theory but I'll take a stab.
I think what is confusing is that its not a time complexity problem, but rather the functions complexity.
So for easy part i just goes up to n ie. 1,2,3 ...n , then for ai all entries must be above 0 meaning that a could be something like this 2,5,1... for n times. If you multiply them together n*n = O(n2).
The best case would be if a is 1,1,1 which drop the complexity down to O(n) but the average case will be n so you get squared.
Unless it's mentioned that a[i] is O(n), it's definitely O(n)
Here an another try to achieve O(n*n) if sum should be returned as result.
int sum = 0;
for(int i = 0; i<=n; i++){
for(int j = 0; j<=n; j++){
if(i == j){
sum += A[i] * j;
}
}
return sum;

Understanding the steps in this sum of subarrays algorithm and its run time

I've been staring at this for a while and it's not sinking in. I think I understand at a basic level what's going on. E.g. A = {1, 2, 3, 4}
Sum = A[0] + [A[0] + A[1]] + [A[0] + A[1] + A[2]] + [A[0] + A[1] + A[2] + A[3]]
However, I'm not able to understand the steps via the explanation/notation below - or at least, it's a little fuzzy. Could someone please explain the steps/walk through what's happening.
Example 1.4 (Sums of subarrays). The problem is to compute, for each subarray a[j..j +m−1] of size m in an array a of size n, the partial sum of its elements s[j] = ∑ m−1 k=0 a[j+k]; j = 0,...,n−m. The total number of these subarrays is n−m+1.
At first glance, we need to compute n−m+1 sums, each of m items, so that the running time is proportional to m(n−m+1). If m is fixed, the time depends still linearly on n. But if m is growing with n as a fraction of n, such as m = n 2, then T(n) = cn 2n 2 +1= 0.25cn2 +0.5cn. The relative weight of the linear part, 0.5cn, decreases quickly with respect to the quadratic one as n increases.
Well, the explanation, you provided seems to be not about your understanding of the problem. I think, your Example 1.4 is really about following.
A = {1, 2, 3, 4}, m = 3.
Sum = (A[0] + A[1] + A[2]) + (A[1] + A[2] + A[3]).
Here you have n-m+1 (4-3+1=2) subsums of m(3) elements each. The described algorithm can be preformed in code like this:
function SumOfSubarrays(A, n, m) {
sum = 0;
//loop for subarrays
for (j = 0; j <= n - m; j++;) {
//loop for elements in each subarray
for (k = 0; k <= m - 1; k++) {
sum += A[j + k];
}
}
}
Time complexity of this algorithm depends linearly on n. But, as it is said in Example 1.4, if m growths as a fraction of n, then time complexity becomes quadratic.
You need totally m(n−m+1) operations: (n−m+1) for outer loop as it is a number of subarrays, m for inner loop as it is a number of elements in each subarray. If m depends on n then you have, for example:
m = 0.5 * n
m(n-m+1) = 0.5n(n-0.5n+1) = 0.5n(0.5n-1) = 0.25n^2 - 0.5n
Where quadratic part growths faster as it is quadratic.

How do I calculate this logarithmic complexity using summations?

My Question
What is the Big-O complexity for this code snippet?
Consider n as a power of 4.
for(int i = 1; i <= n; i = i*4)
for(int k = 1; k <= i; k++)
// constant statement
What I know so far
I tried making this code into a summation to find the complexity.
This is what I got:
I got (base 4) log(n) by computing the series 4, 4^2, 4^3 ... 4^r = n.
r = (base 4) log(n).
I'm now stuck at this summation:
Please let me know If I'm doing something wrong or there is another way to do this.
You’re on the right track here, but your innermost summation is wrong. You are right that the outer loop will iterate log_4 n times, but you’ve set up the outer sum so that i counts up as 1, 2, 3, ..., log_4 n, rather than 4^0, 4^1, 4^2, ... 4^log_4 n. As a result, that inner summation’s upper bound is incorrect. The bound should be 4^i, not i.
If you set things up this way, you’ll find that the overall sum is
4^0 + 4^1 + 4^2 + ... + 4^log_4 n
= (4^(log_4 n + 1) - 1) / (4 - 1) (using the formula for the sum of a geometric series
= (4(4^log_4 n) - 1) / 3
= (4n - 1) / 3
= Θ(n).
You may use wolframalpha to get the result for extreme accuracy.
https://www.wolframalpha.com/input/?i=sum+i,+i%3D1+to+log_4(n)

Time complexity of following code with explanation?

What is the time complexity of this algorithm, and why?
int count = 0;
for (int i = N; i > 0; i /= 2) {
for (int j = 0; j < i; j++) {
count += 1;
}
}
The correct answer is O(n), but I am getting O(nlogn). Can anyone tell me why it's O(n)?
On the first iteration, the inner loop executes N times, and then N/2 times, and then N/4 times, and so on. This can be expressed as an infinite sum:
N + N/2 + N/4 + N/8 + N/16 + N/32 + ...
If you factor out the N from each term, you get:
N * (1 + 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + ...)
The infinite sequence in parentheses converges on the value 2 (more info on Wikipedia). Therefore, the number of operations can be simplified to:
N * 2
In terms of Big-O, the asymptotic value is within:
O(N)
You can check this by observing that the relationship in the output between N and count is linear: Ideone Demo

Resources