Exponentiation complexity - c

Based on this code:
int poow(int x,int y)
{
if(y==0)
return 1;
if(y%2!= 0)
return poow(x,y-1)*x;
return poow(x,y/2)*poow(x,y/2); //this line
}
I tried to see the complexity: We suppose that we have n=2^k
we have T(0)=1
T(n)=2*T(n/2)+C
T(n)=2^i * T(n/2^i)+i*c
for i=k we have T(n)=2^k * T(n/2^k) + k * c
T(n)=2^k * T(1) + k*c
T(n)=2^k * c2 + k * c
I am stuck here ? How can I continue the computation of complexity and what is the difference when changing this line:
return poow(x,y/2)*poow(x,y/2); //this line
with
int p=poow(x,y/2);
return p*p;
in term of complexity !

Start off with a proper recurrence. The complexity is solely based on y, so we can write the recurrence as
T(0) = 1
T(y) = y is even: 2 * T(y / 2)
y is odd: T(y - 1) + 1
Worst-case would be that every division by 2 leaves us with a odd number, which would lead to the complexity of
T(2^n-1) = 1 + 2 * (1 + 2 * (1 + 2 * ( ... * T(1)))) =
= 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ... + 2 ^ (n - 1) + 2 ^ (n - 1) =
= 2 ^ n - 1 + 2 ^(n - 1) = 3 * 2 ^ (n - 1) - 1
T(y) = O(y)
Best-case would be a power of 2:
T(2^n) = 2 * 2 * ... * 2 * T(1) = 2 ^ n * (1 + 1) = 2 ^ (n + 1) = 2 * 2 ^ n
T(y) = O(y)
Now what if we optimized the whole function?
T'(0) = 1
T'(y) = y is even: T(y / 2) + 1
y is odd: T(y - 1) + 1
Worst case:
T'(2^n - 1) = T(2^n - 2) + 1 = T(2^(n - 1) - 1) + 1 + 1 = ... =
= T(1) + 1 + 1 + 1 + ... =
= 2 + 1 + 1 + 1 + ... =
= 1 + ln(2^n) / ln(2) * 2 =
= 1 + 2 * n
T'(y) = O(log y)
Best case:
T'(2 ^ n) = T(1) + 1 + 1 + ... =
= 2 + 1 + 1 + ... =
= 2 + ln(2^n) / ln(2)
= n + 2
T'(y) = O(log y)
So the optimized version is definitely faster (linear vs logarithmic complexity).

Sometime code analysis focuses on the theory and not the actual.
Code has a bug.
if(y%2!= 0)
return poow(x,y-1)*x;
// should be
if(y%2!= 0)
return poow(x,y-y%2)*x;
// better alternative, use
unsigned poow(unsigned x, unsigned y)
Without the fix, calling poow(1,-1) causes infinite recursion and likely stack-overflow. So O(∞) regardless in the last line is return poow(x,y/2)*poow(x,y/2); or int p=poow(x,y/2);
return p*p;.

Related

Sum of subarray multiplied by last element of subarray

Given an array find all sub-arrays and multiply it by last element of sub-array and find summation .
E.g : [1,2,3]
ans = 1*1 + 2*2 +3*3 + (1+2)*2 + (2+3)*3 + (1+2+3)*3 = 53
I've tried following logic:
init_sum = sum (array)
prev = array[0];
ans = 0
for i = 1 to n:
ans += array[i]* array[i]*(init_sum-prev)
init_sum -= prev
prev = array[i]
end loop
ans += sum(array)
print(ans)
But this does not work for array with repeated elements
E.g : [1,3,3] , I'm getting ans = 88 where it should be 70.
Any hint would be appreciated .
There is a recursive formula for each element of the array.
For each element ith, we can notice that the contribution of this element to the overall sum is equaled to the sum of all sub array that end at this element times the value of this element itself.
I.e
For array data[a, b, c, d], the result will be:
result = a * a
+ ((a + b) + b) * b
+ ((a + b + c) + (b + c) + c) * c
+ ((a + b + c + d) + (b + c + d) + (c + d) + d) * d
Call the factor to be multiplied with the value of ith element is xi, we make one observation that
xi = x(i - 1) + i*data[i]
So, in case of the above array
x1 = a
x2 = ((a + b) + b) = x1 + 2*b
x3 = ((a + b + c) + (b + c) + c) = x2 + 3*c
x4 = ((a + b + c + d) + (b + c + d) + (c + d) + d) = x3 + 4*d
Thus, we have our solution
init_sum = 0
ans = 0
for i = 0 to n:
init_sum = init_sum + (i + 1)*array[i]
ans += init_sum*array[i]
end loop
print(ans)
The algorithm you are after can be divided into the following steps:
1- Generate the power set of the given array.
2- For each set, add each element in the array, pick the last element in the current set and add multiply it with the sum of the set. Add this sum to the totalsum
Lets see this in action for [1 3 3], I use the algorithm below to generate the power set and store it in res
Step 1:
void generateSubsets(int i, vector<int>& nums, vector<int>& holder, vector<vector<int>>& res)
{
if(i >= nums.size())
{
res.push_back(holder);
return;
}
holder.push_back(nums[i]);
generateSubsets(i+1,nums,holder,res);
holder.pop_back();
generateSubsets(i+1,nums,holder,res);
}
Where I call this function as:
vector<vector<int>> res;
vector<int> holder;
vector<int> nums = {1,3,3};
generateSubsets(0,nums,holder,res);
The generated subsets in res are:
[1 3 3],[1 3],[1 3],[1],[3 3],[3],[3]
Step 2 : Add each element in the set and multiply by last element of the set, so we have.
[1+3+3]*3 + [1+3]*3 + [1+3]*3 + [1]*1 + [3*3]*3 + [3]*3 + [3]*3
Cumulative totalsum will then be:
totalsum = 21 + 12 + 12 + 1 + 18 + 3 + 3 = 70

What is the running time complexity of the following piece of code?

void foo(int n){
int i = 1, sum = 1;
while (sum <= n) {
i++;
sum+=i;
}
}
What I feel is, the loop will terminate only if the sum becomes greater than the argument n.
And, Sum at jth iteration is: S(j) = S(j-1) + j
S(1) = S(0) + 1
S(2) = S(1) + 2
S(3) = S(2) + 3
...
S(n) = S(n-1) + n
How should I go further? I am stuck at this recurrence relation.
The loop will terminate when 1 + 2 + 3 + ... + j times becomes greater than n. But I am not convinced, if it is okay.
The classic way to prove this is to write the series out twice, in both orders ie:
S(n) = 1 + 2 + 3 + ...+ n-2 + n-1 + n
S(n) = n + (n-1) + (n-2) + ...+ 3 + 2 + 1
If you sum those term by term you get
2S(n)= n+1 + n+1 + n+1 + ... + n+1
With n terms
therefore
S(n) = n*(n+1)/2
(A result allegedly discovered by Gauss as a schoolboy)
From this it follows that it takes O(sqrt(n)) iterations.
You have almost done it. The last thing you have to note is that 1 + 2 + 3 + ... + j is (1 + j) * j / 2, or O(j^2). This is a well-known formula from math (arithmetic progression).
It will break after k iterations when
1 + 2 + .... + k > n
k*(k+1)/2 > n
k*k + k - 2*n >0
k will come to k = (-1 + sqrt(1+8n))/2 (discarding negative value)
Hence, Time complexity is sqrt(n).

Large array indexes scala

(Language: scala)
I have a problem where I want to iterate over 1 million numbers, but for some reason I get an arrayindexOutofbounds exception. The function I am using works perfectly for 100 000 numbers, but I get the exception if I add a zero.
There cannot be a problem with the array size, because I have built a sort of flex-array, where the array is about 1000 elements and each element consists of a list of elements.
So the problem looks something like this:
for (x <- 1 to 1000000) {
// Do a thing
}
Can for loops only handle a certain number of elements?
I have tried running the program with the "extra-space-flag"
I include the whole code below for reference, in case it makes a difference
object Problem14 {
class FlexArray (n : Int){
var array = new Array[List[Tuple2[Int, Int]]](n)
val size = n
for(x <- 0 until size) {
array(x) = List()
}
def insert (n : Int, value : Int) {
if (find(n) != -1) {
val i = n % size
array(i) = (n, value) :: array(i)
}
}
def read (i : Int) : List[Tuple2[Int, Int]] = {
(array(i))
}
def findAux (list : List[Tuple2[Int, Int]], n : Int) : Int = {
if (list == Nil) {
-1
} else {
val (num, value) = list.head
if (n == num) {
value
} else {
findAux(list.tail, n)
}
}
}
def find (n : Int) : Int = {
val i = n % size
findAux(array(i), n)
}
}
var accArray = new FlexArray(10000)
// denna funktion bör kallas med 1 som andra argument
def chainLength (n : Int, acc : Int) : Int = {
if (n == 1)
acc
else {
val value = accArray.find(n)
if (value != -1)
acc + value
else if (n % 2 == 0)
chainLength(n/2, acc+1)
else
chainLength(3*n+1, acc+1)
}
}
def main(args: Array[String]) {
var max = 0
var maxnum = 0
for (x <- 1 to 1000000) {
var value = chainLength(x, 1)
accArray.insert(x, value)
if (max < value) {
max = value
maxnum = x
}
println(maxnum + ": " + max)
}
}
The problem isn't with array indexes, scala functions just like java and will go to Int.MaxValue 2,147,483,647. The problem is with this line of in your chainLength function:
chainLength(3 * n + 1, acc + 1)
Since chainLength is recursive on itself switching between n/2 and n * 3 + 1 you run into this with numbers larger than 113383. It leads to integer overflow so you end up with a negative value passed to the array index which throws your error. I'm guessing you'll need to add some integer overflow handling to your function.
Full output of calls to chainLength in chainLength(113383, 1) (it ends with overflow at the bottom):
Starting at 113383
3 * 113383 + 1 = 340150
340150 / 2 = 170075
3 * 170075 + 1 = 510226
510226 / 2 = 255113
3 * 255113 + 1 = 765340
765340 / 2 = 382670
382670 / 2 = 191335
3 * 191335 + 1 = 574006
574006 / 2 = 287003
3 * 287003 + 1 = 861010
861010 / 2 = 430505
3 * 430505 + 1 = 1291516
1291516 / 2 = 645758
645758 / 2 = 322879
3 * 322879 + 1 = 968638
968638 / 2 = 484319
3 * 484319 + 1 = 1452958
1452958 / 2 = 726479
3 * 726479 + 1 = 2179438
2179438 / 2 = 1089719
3 * 1089719 + 1 = 3269158
3269158 / 2 = 1634579
3 * 1634579 + 1 = 4903738
4903738 / 2 = 2451869
3 * 2451869 + 1 = 7355608
7355608 / 2 = 3677804
3677804 / 2 = 1838902
1838902 / 2 = 919451
3 * 919451 + 1 = 2758354
2758354 / 2 = 1379177
3 * 1379177 + 1 = 4137532
4137532 / 2 = 2068766
2068766 / 2 = 1034383
3 * 1034383 + 1 = 3103150
3103150 / 2 = 1551575
3 * 1551575 + 1 = 4654726
4654726 / 2 = 2327363
3 * 2327363 + 1 = 6982090
6982090 / 2 = 3491045
3 * 3491045 + 1 = 10473136
10473136 / 2 = 5236568
5236568 / 2 = 2618284
2618284 / 2 = 1309142
1309142 / 2 = 654571
3 * 654571 + 1 = 1963714
1963714 / 2 = 981857
3 * 981857 + 1 = 2945572
2945572 / 2 = 1472786
1472786 / 2 = 736393
3 * 736393 + 1 = 2209180
2209180 / 2 = 1104590
1104590 / 2 = 552295
3 * 552295 + 1 = 1656886
1656886 / 2 = 828443
3 * 828443 + 1 = 2485330
2485330 / 2 = 1242665
3 * 1242665 + 1 = 3727996
3727996 / 2 = 1863998
1863998 / 2 = 931999
3 * 931999 + 1 = 2795998
2795998 / 2 = 1397999
3 * 1397999 + 1 = 4193998
4193998 / 2 = 2096999
3 * 2096999 + 1 = 6290998
6290998 / 2 = 3145499
3 * 3145499 + 1 = 9436498
9436498 / 2 = 4718249
3 * 4718249 + 1 = 14154748
14154748 / 2 = 7077374
7077374 / 2 = 3538687
3 * 3538687 + 1 = 10616062
10616062 / 2 = 5308031
3 * 5308031 + 1 = 15924094
15924094 / 2 = 7962047
3 * 7962047 + 1 = 23886142
23886142 / 2 = 11943071
3 * 11943071 + 1 = 35829214
35829214 / 2 = 17914607
3 * 17914607 + 1 = 53743822
53743822 / 2 = 26871911
3 * 26871911 + 1 = 80615734
80615734 / 2 = 40307867
3 * 40307867 + 1 = 120923602
120923602 / 2 = 60461801
3 * 60461801 + 1 = 181385404
181385404 / 2 = 90692702
90692702 / 2 = 45346351
3 * 45346351 + 1 = 136039054
136039054 / 2 = 68019527
3 * 68019527 + 1 = 204058582
204058582 / 2 = 102029291
3 * 102029291 + 1 = 306087874
306087874 / 2 = 153043937
3 * 153043937 + 1 = 459131812
459131812 / 2 = 229565906
229565906 / 2 = 114782953
3 * 114782953 + 1 = 344348860
344348860 / 2 = 172174430
172174430 / 2 = 86087215
3 * 86087215 + 1 = 258261646
258261646 / 2 = 129130823
3 * 129130823 + 1 = 387392470
387392470 / 2 = 193696235
3 * 193696235 + 1 = 581088706
581088706 / 2 = 290544353
3 * 290544353 + 1 = 871633060
871633060 / 2 = 435816530
435816530 / 2 = 217908265
3 * 217908265 + 1 = 653724796
653724796 / 2 = 326862398
326862398 / 2 = 163431199
3 * 163431199 + 1 = 490293598
490293598 / 2 = 245146799
3 * 245146799 + 1 = 735440398
735440398 / 2 = 367720199
3 * 367720199 + 1 = 1103160598
1103160598 / 2 = 551580299
3 * 551580299 + 1 = 1654740898
1654740898 / 2 = 827370449
3 * 827370449 + 1 = -1812855948

A puzzle related to nested loops

For a given input N, how many times does the enclosed statement executes?
for i in 1 … N loop
for j in 1 … i loop
for k in 1 … j loop
sum = sum + i ;
end loop;
end loop;
end loop;
Can anyone figure out an easy way or a formula to do this in general. Please explain.
First, I written a C code to generate sum:
int main(){
int i =0, k =0, j =0, n =0;
int N =0;
int sum =0;
N =10;
for (n=1; n <= N; n++){
// unindented code here
sum =0;
for (i=1; i<=n; i++)
for (j=1; j<=i; j++)
for (k=1; k<=j; k++)
sum++;
printf("\n N=%d sum = %d",n, sum);
}
printf("\n");
}
Simple compile and generate result for N=1 to N=10 :
$ gcc sum.c
$ ./a.out
N=1 sum = 1
N=2 sum = 4
N=3 sum = 10
N=4 sum = 20
N=5 sum = 35
N=6 sum = 56
N=7 sum = 84
N=8 sum = 120
N=9 sum = 165
N=10 sum = 220
Then, Tried to explore How this works? with some diagrams:
For, N=1:
i<=N, (i=1)
|
j<=i, (j=1)
|
k<=j, (K=1)
|
sum=0. sum++ ---> sum = 1
That is (1) = 1
For, N=2:
i<=N, (i=1)-------(i=2)
| |-----|-----|
j<=i, (j=1) (j=1) (j=2)
| | |----|----|
k<=j, (K=1) (K=1) (K=1) (K=2)
| | | |
sum=0, sum++ sum++ sum++ sum++ --> sum = 4
That is (1) + (1 + 2) = 4
For, N=3:
i<=N, (i=1)-------(i=2)--------------------(i=3)
| |-----|-----| |---------|-------------|
j<=i, (j=1) (j=1) (j=2) (j=1) (j=2) (j=3)
| | |----|----| | |----|----| |-----|-----|
k<=j, (K=1) (K=1) (K=1) (K=2) (K=1) (K=1) (K=2) (K=1) (K=2) (K=3)
| | | | | | | | | |
sum=0, sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++ sum++
--> sum = 10
That is (1) + (1 + 2) + ( 1 + 2 + 3 ) = 10
N = 1, (1) = 1
N = 2, (1) + (1 + 2) = 4
N = 3, (1) + (1 + 2) + (1 + 2 + 3) = 10
N = 4, (1) + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) = 20
N = 5, (1) + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3 + 4) + (1 + 2 + 3 + 4 + 5) = 35
Finally, I could understood that sum of N in three loop is:
(1) + (sum 0f 1 to 2) + ... + (sum of 1 to (N-2)) + (sum of 1 to (N-1) ) + (sum of 1 to N)
or we can write it as:
=> (1) + (1 + 2) + ...+ (1 + 2 +....+ i) + ... + (1 + 2 + ....+ N-1) + (1 + 2 + ....+ N)
=> ( N * 1 ) + ( (N-1) * 2) + ( (N-2) * 3) +...+ ( (N -i+1) * i ) +... + ( 1 * N)
You can refer here for simplification calculations: (I asked HERE )
[YOUR ANSWER]
= ( ((N) * (N+1) * (N+2)) / 6 )
And, I think its correct. I checked as follows:
N = 1, (1 * 2 * 3)/6 = 1
N = 2, (2 * 3 * 4)/6 = 4
N = 3, (3 * 4 * 5)/6 = 6
N = 4, (4 * 5 * 6)/6 = 10
N = 5, (5 * 6 * 7)/6 = 35
Also, The complexity of this algorithm is O(n3)
EDIT:
The following loop also has same numbers of count, that is = ( ((N) * (N+1) * (N+2)) / 6 )
for i in 1 … N loop
for j in i … N loop
for k in j … N loop
sum = sum + i ;
end loop;
end loop;
end loop;

Understanding CEILING macro use cases

I've found the following macro in a utility header in our codebase:
#define CEILING(x,y) (((x) + (y) - 1) / (y))
Which (with help from this answer) I've parsed as:
// Return the smallest multiple N of y such that:
// x <= y * N
But, no matter how much I stare at how this macro is used in our codebase, I can't understand the value of such an operation. None of the usages are commented, which seems to indicate it is something obvious.
Can anyone offer an English explanation of a use-case for this macro? It's probably blindingly obvious, I just can't see it...
Say you want to allocate memory in chunks (think: cache lines, disk sectors); how much memory will it take to hold an integral number of chunks that will contain the X bytes? If the chuck size is Y, then the answer is: CEILING(X,Y)
When you use an integer division in C like this
y = a / b
you get a result of division rounded towards zero, i.e. 5 / 2 == 2, -5 / 2 == -2. Sometimes it's desirable to round it another way so that 5 / 2 == 3, for example, if you want to take minimal integer array size to hold n bytes, you would want n / sizeof(int) rounded up, because you want space to hold that extra bytes.
So this macro does exactly this: CEILING(5,2) == 3, but note that it works for positive y only, so be careful.
Hmm... English example... You can only buy bananas in bunches of 5. You have 47 people who want a banana. How many bunches do you need? Answer = CEILING(47,5) = ((47 + 5) - 1) / 5 = 51 / 5 = 10 (dropping the remainder - integer division).
Let's try some test values
CEILING(6, 3) = (6 + 3 -1) / 3 = 8 / 3 = 2 // integer division
CEILING(7, 3) = (7 + 3 -1) / 3 = 9 / 3 = 3
CEILING(8, 3) = (8 + 3 -1) / 3 = 10 / 3 = 3
CEILING(9, 3) = (9 + 3 -1) / 3 = 11 / 3 = 3
CEILING(10, 3) = (9 + 3 -1) / 3 = 12 / 3 = 4
As you see, the result of the macro is an integer, the smallest possible z which satisfies: z * y >= x.
We can try with symbolics, as well:
CEILING(k*y, y) = (k*y + y -1) / y = ((k+1)*y - 1) / y = k
CEILING(k*y + 1, y) = ((k*y + 1) + y -1) / y = ((k+1)*y) / y = k + 1
CEILING(k*y + 2, y) = ((k*y + 2) + y -1) / y = ((k+1)*y + 1) / y = k + 1
....
CEILING(k*y + y - 1, y) = ((k*y + y - 1) + y -1) / y = ((k+1)*y + y - 2) / y = k + 1
CEILING(k*y + y, y) = ((k*y + y) + y -1) / y = ((k+1)*y + y - 1) / y = k + 1
CEILING(k*y + y + 1, y) = ((k*y + y + 1) + y -1) / y = ((k+2)*y) / y = k + 2
You canuse this to allocate memory with a size multiple of a constant, to determine how many tiles are needed to fill a screen, etc.
Watch out, though. This works only for positive y.
Hope it helps.
CEILING(x,y) gives you, assuming y > 0, the ceiling of x/y (mathematical division). One use case for that would be a prime sieve starting at an offset x, where you'd mark all multiples of the prime y in the sieve range as composites.

Resources