I have the following pseudo-code which I want to determine its run-time T(n).
Can someone please give me the steps I should follow ?
Here is the code:
i := 1;
while (i <= n)
j := i;
x := x+A[i];
while (j > 0)
y := x/(2*j);
j = j /2; // Assume here that this returns the floor of the quotient
i = 2 * i;
return y;
I think it's O(log log N) if my calculation is not wrong.
First, we omit the lines that does not affect the loop times, also assume array random visit as O(1).
i := 1;
while (i <= n)
j := i;
while (j > 0)
j = j / 2;
i = 2 * i;
return y;
Then we assume that all the operations in one line are done in O(1), we add them up and get the result.
Besides the math analysis, we can also use computational: we run the fragment for several times and see the time growth (I also omitted the operations that does not affect the loop times).
#include <iostream>
using namespace std;
int main(){
long long i, j, n;
double cost;
clock_t start, finish;
i = 1;
n = 1000000000000;
start = clock();
while (i <= n) {
j = i;
while (j > 0) {
j = j / 2;
}
i = 2 * i;
}
finish = clock();
cout << (double)(finish - start)/CLOCKS_PER_SEC << endl;
}
Related
int i = 0;
int n = 20;
while (i < n)
{
i++;
int j = i;
while (i < n)
{
printf("this is %d", i);
i++;
}
i = j;
}
So to estimate the time complexity of this function, my approach to estimating is that the outer loop runs n times. The inner loop runs n - 1 times? so would the time complexity for this nested loop be O(n^2)?
You can rewrite the initial code
int n = 20;
int i = 0;
while (i < n)
{
i++;
int j = i;
while (i < n)
{
printf("this is %d",i);
i++;
}
i = j;
}
into its equivalent:
int n = 20;
for (int i = 1; i < n; ++i)
for (int j = i; j < n; ++j)
printf("this is %d", j);
Now it's evident that you have O(n**2) time complexity: you have
(n - 1) + (n - 2) + (n - 3) + ... + 3 + 2 + 1 = n * (n - 1) / 2
operations (printf(...)) and
O(n * (n - 1) / 2) = O(n**2 / 2 - n / 2) = O(n**2)
In subsequent iterations, inner loop runs as many times as n-1, n-2, n-3,..., 1. So the sum is n(n-1)/2, which leads to the asymptotic time complexity as O(n^2).
This algorithm seems to work after a few tries but I'm not sure if it's right. Can anyone help?
n is the size of the array
i goes from the first case to the case number (n-1)
j goes from i+1 to n
#include <stdio.h>
#include <stdlib.h>
void main() {
int t[50];
int i;
int j;
int n;
int aux;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
scanf("%d", &t[i]);
}
for (i = 1; i <= n - 1; i++) {
for (j = i + 1; j <= n; j++) {
if (t[i] > t[j]) {
aux = t[i];
t[i] = t[j];
t[j] = aux;
}
}
}
for (i = 1; i <= n; i++) {
printf("|| %d", t[i]);
}
}
Looks like in pseudocode, your algorithm is the following:
Sort(A, N):
for (i = 1 to N-1):
for (j = i+1 to N):
if (A[i] > A[j]):
swap(A, i, j)
where A is the array of numbers and N is the array size.
It's been a while since I tried proving the correctness of anything, but it seems that if the outer loop can guarantee that at the end of each iteration, the smallest number will be at A[i], it will be correct. So the question is whether or not the inner loop puts the smallest element in A[i].
Since it swaps A[i] with A[j] every time A[i] is larger than A[j], we can guarantee that A[k-1] is always larger than A[i] at any k-th iteration of the inner loop, and therefore A[i] will be the smallest element for the subarray A[i:N] by the time the inner loop finishes executing (when k = N+1). Therefore, this algorithm is correct.
I am not too familiar with C programming so I can't tell you if your code exactly follows this, but if it does, then your code sample is also correct.
I am solving the problem to find the maximum number of max heaps that can be formed using n distinct integers (say 1..n). I have solved it using the following
recurrence with some help from this: https://www.quora.com/How-many-Binary-heaps-can-be-made-from-N-distinct-elements :
T(N) = N-1 (C) L * T(L) * T(R). where L is the number of nodes in the left subtree and R is the number of nodes in the right subtree. I have also implemented it in c++ using dynamic programming. But I am stuck in find the time complexity of it. Can someone help me with this?
#include <iostream>
using namespace std;
#define MAXN 105 //maximum value of n here
int dp[MAXN]; //dp[i] = number of max heaps for i distinct integers
int nck[MAXN][MAXN]; //nck[i][j] = number of ways to choose j elements form i elements, no order */
int log2[MAXN]; //log2[i] = floor of logarithm of base 2 of i
//to calculate nCk
int choose(int n, int k)
{
if (k > n)
return 0;
if (n <= 1)
return 1;
if (k == 0)
return 1;
if (nck[n][k] != -1)
return nck[n][k];
int answer = choose(n-1, k-1) + choose(n-1, k);
nck[n][k] = answer;
return answer;
}
//calculate l for give value of n
int getLeft(int n)
{
if (n == 1)
return 0;
int h = log2[n];
//max number of elements that can be present in the hth level of any heap
int numh = (1 << h); //(2 ^ h)
//number of elements that are actually present in last level(hth level)
//(2^h - 1)
int last = n - ((1 << h) - 1);
//if more than half-filled
if (last >= (numh / 2))
return (1 << h) - 1; // (2^h) - 1
else
return (1 << h) - 1 - ((numh / 2) - last);
}
//find maximum number of heaps for n
int numberOfHeaps(int n)
{
if (n <= 1)
return 1;
if (dp[n] != -1)
return dp[n];
int left = getLeft(n);
int ans = (choose(n-1, left) * numberOfHeaps(left)) * (numberOfHeaps(n-1-left));
dp[n] = ans;
return ans;
}
//function to intialize arrays
int solve(int n)
{
for (int i = 0; i <= n; i++)
dp[i] = -1;
for (int i = 0; i <= n; i++)
for (int j = 0; j <=n; j++)
nck[i][j] = -1;
int currLog2 = -1;
int currPower2 = 1;
//for each power of two find logarithm
for (int i = 1; i <= n; i++)
{
if (currPower2 == i)
{
currLog2++;
currPower2 *= 2;
}
log2[i] = currLog2;
}
return numberOfHeaps(n);
}
//driver function
int main()
{
int n=10;
cout << solve(n) << endl;
return 0;
}
I believe that the following code is big theta of n^3, is this correct?
for (int i = 0; i < n; i ++)
{ // A is an array of integers
if (A[i] == 0) {
for (int j = 0; j <= i; j++) {
if (A[i] == 0) {
for (int k = 0; k <= j; k++) {
A[i] = 1;
}
}
}
}
}
And that the following is big theta of nlog(n)
for (int i = 1; i < n; i *= 2)
{
func(i);
}
void func(int x) {
if (x <= 1) return;
func(x-1);
}
because the for loop would run log(n) times, and func runs at most n recursive calls.
Thanks for the help!
Your intuition looks correct. Note that for the first bit if the input contains non-zero elements the time complexity drops down to big-theta(n). If you remove the checks it would definitely be big-theta(n^3).
You are correct about the second snippet, however the first is not Big-Theta(n^3). It is not even O(n^3)! The key observation is: for each i, the innermost loop will execute at most once.
Obviously, the worst-case is when the array contains only zeros. However, A[i] will be set to 1 in the first pass of the inner-most loop, and all subsequent checks of if (A[i] == 0) for the same i will be evaluated to false and the innermost loop will not be executed anymore until i increments. Therefore, there are total of 1 + 2 + 3 + .. + n = n * (n + 1) / 2 iterations, so the time complexity of the first snippet is O(n^2).
Hope this helps!
We are given a sequence of n positive integers, which I will denote as a0, a1, …, an-1. We are also given an integer k, and our task is to:
find a subsequence of length exactly k (denoted as b0, b1, …, bk-1), such that abs(b1 - b0) + abs(b2 - b1) + … + abs(bk-1 - bk-2) is maximal; and
output the sum (no need to output the entire subsequence).
I have been trying to solve this using a dynamic programming approach but all my efforts have been futile.
EDIT: k <= n. The elements in the sequence b must appear in the same order as they appear in a (otherwise, this would be solved by simply finding max, min, ... or min, max, ...).
Example input:
n = 10
k = 3
1 9 2 3 6 1 3 2 1 3
Output:
16 (the subsequence is 1 9 1, and abs(9 - 1) + abs(1 - 9) = 8 + 8 = 16)
Any help / hints would be greatly appreciated.
I managed to solve this problem. Here's the full code:
#include <stdio.h>
#include <stdlib.h>
int abs(int a)
{
return (a < 0) ? -a : a;
}
int solve(int *numbers, int N, int K)
{
int **storage = malloc(sizeof(int *) * N);
int i, j, k;
int result = 0;
for (i = 0; i < N; ++i)
*(storage + i) = calloc(K, sizeof(int));
// storage[i][j] keeps the optimal result where j + 1 elements are taken (K = j + 1) with numbers[i] appearing as the last element.
for (i = 1; i < N; ++i) {
for (j = 1; j < K; ++j) {
for (k = j - 1; k < i; ++k) {
if (storage[i][j] < storage[k][j - 1] + abs(numbers[k] - numbers[i]))
storage[i][j] = storage[k][j - 1] + abs(numbers[k] - numbers[i]);
if (j == K - 1 && result < storage[i][j])
result = storage[i][j];
}
}
}
for (i = 0; i < N; ++i)
free(*(storage + i));
free(storage);
return result;
}
int main()
{
int N, K;
scanf("%d %d", &N, &K);
int *numbers = malloc(sizeof(int) * N);
int i;
for (i = 0; i < N; ++i)
scanf("%d", numbers + i);
printf("%d\n", solve(numbers, N, K));
return 0;
}
The idea is simple (thanks to a friend of mine for hinting me at it). As mentioned in the comment, storage[i][j] keeps the optimal result where j + 1 elements are taken (K = j + 1) with numbers[i] appearing as the last element. Then, we simply try out each element appearing as the last one, taking each possible number of 1, 2, ..., K elements out of all. This solution works in O(k * n^2).
I first tried a 0-1 Knapsack approach where I kept the last element I had taken in each [i][j] index. This solution did not give a correct result in just a single test case, but it worked in O(k * n). I think I can see where it would yield a suboptimal solution, but if anyone is interested, I can post that code, too (it is rather messy though).
The code posted here passed on all test cases (if you can detect some possible errors, feel free to state them).