How to find recursive relation of this recursive function? - java

Here I got a function like this and I want to find the recursive relation of that and after that calculate time complexity of that recursive relation.
public static void f(int n) {
if (n == 1) {
//" Do sth "
} else {
for (int i = 1; i < n; i++) {
f(i - 1);
//" Do sth "
}
}
}
actually I tried a lot for that and I got T(n) = n * f( n-1) for this function as the relation but I am not sure about that . could you help me find the correct relation and solve it ?

Assuming T(1) = "Do sth" is constant work i.e. it doesn't depend on the input size n, you could write the recursive time function as :
T(n) = T(1) + T(2) + ... + T(n-1)
= { T(1) } + { T(1) } + { T(1) + T(2) } + { T(1) + T(2) + T(3) } + { T(1) + T(2) + T(3) + T(4) } +....
[let T(1) = x]
= x + x + {x + x} + {x + x + (x + x)} + {x + x + (x + x) + x + x + (x + x)} +....
= x + x + 2x + 4x + 8x + ...
~ x.2^(n-2)
~ O(2^n)
Here is a python program to demonstrate the sequence of coefficients for the summation:
t = [0 for i in range(10)]
for i in range(1,10):
if i == 1:
t[i] = 1
else:
val = 0
for j in range(1,i):
val += t[j]
t[i] = val
print(t[1:])
prints : [1, 1, 2, 4, 8, 16, 32, 64, 128]
You can see that 2(n-2) for n >= 2 holds good at each 'n' and complexity is O(2n)

Related

Recursively find combinations of three numbers that sum up to given number

Given a number between 1 and 30, find all three-number combinations that sum up to this number and return the amount of combinations without using loops.
for example, given 5, print
1 + 1 + 3
1 + 2 + 2
1 + 3 + 1
2 + 1 + 2
2 + 2 + 1
3 + 1 + 1
This is what I have right now, using Java.
private static int numbers(int num, int num1, int num2, int num3){
boolean valid_solution = num1+num2+num3 == num;
int counter = 0;
if (valid_solution){
System.out.println(num1+" + "+num2+" + "+num3);
counter++;
}
if (num1>10 || num2>10 || num3>10 || num1+num2+num3>num){
return counter;
}
counter += numbers(num, num1 + 1, num2, num3)+numbers(num, num1, num2 + 1, num3)+numbers(num, num1, num2, num3 + 1);
return counter;
}
public static int solutions(int num){
if (num < 0 || num > 30) return 0;
return numbers(num, 1, 1, 1);
}
I seem to get duplicates, for example for 5-
3 + 1 + 1
2 + 2 + 1
2 + 1 + 2
2 + 2 + 1
1 + 3 + 1
1 + 2 + 2
2 + 1 + 2
1 + 2 + 2
1 + 1 + 3
edit - I'm also not allowed to use global variables.
You can see why the duplicates are happening if you add a little logging
1:1:1
2:1:1
3:1:1
3 + 1 + 1
4:1:1
3:2:1
3:1:2
2:2:1
2 + 2 + 1
3:2:1
2:3:1
2:2:2
2:1:2
2 + 1 + 2
3:1:2
2:2:2
2:1:3
1:2:1
2:2:1
2 + 2 + 1
3:2:1
2:3:1
2:2:2
1:3:1
1 + 3 + 1
2:3:1
1:4:1
1:3:2
1:2:2
1 + 2 + 2
2:2:2
1:3:2
1:2:3
1:1:2
2:1:2
2 + 1 + 2
3:1:2
2:2:2
2:1:3
1:2:2
1 + 2 + 2
2:2:2
1:3:2
1:2:3
1:1:3
1 + 1 + 3
2:1:3
1:2:3
1:1:4
counter:9
so since you are making recursive calls on incrementing numbers, when you're recursively calling num2+1, you want to make sure that num1 is less than or equal to num2 in order to avoid duplicates
I have a suspicions that this code of mine is far from being a good solution, but who knows, may be it will be helpful for you in some way.
public class FindSumCombinations {
static int start = 5;
static int comb1 = 0;
static int comb2 = 0;
public static void main(String[] args) {
comb1(start);
}
public static int comb1(int x){
if(x == 0) return 0;
comb1 = x;
comb2(x);
return comb1(x-1);
}
public static int comb2(int x){
if(x == 0) return 0;
comb2 = x;
comb3(x);
return comb2(x-1);
}
public static int comb3(int x){
if(x == 0) return 0;
if(x + comb2 + comb1 == start){
System.out.println(comb1 + "+" + comb2 + "+" + x);
System.out.println(x + "+" + comb1 + "+" + comb2);
System.out.println(comb2 + "+" + x + "+" + comb1);
}
return comb3(x-1);
}
}

BigInteger.pow() doesn't work until last 2 iterations?

I have the following code
public static void main(String[] args) {
BigInteger iter = BigInteger.valueOf(140);
BigInteger y = BigInteger.valueOf(1114112);
BigInteger sum = BigInteger.valueOf(0);
while(iter.intValue() != 0) {
BigInteger z = BigInteger.valueOf((y.pow(iter.intValue())).longValue());
sum = sum.add(z);
iter = iter.subtract(BigInteger.valueOf(1));
System.out.println("Itereration: " + (140 - iter.longValue()));
System.out.println("Y: " + y.longValue());
System.out.println("Z: " + z.longValue());
System.out.println("Sum: " + sum.longValue());
}
}
However, the output is this (only last 3 iterations)
Iteration: 137
Y: 1114112
Z: 0
Sum: 0
Iteration: 138
Y: 1114112
Z: 1382886560579452928
Sum: 1382886560579452928
Iteration: 139
Y: 1114112
Z: 1241245548544
Sum: 1382887801825001472
Iteration: 140
Y: 1114112
Z: 1114112
Sum: 1382887801826115584
The rest of iterations 1-136 are the same as iteration 137
The .longValue() calls do completely wrong things on BigInteger values this large. If you tried using .longValueExact() instead, you'd see that it throws an exception because the values are out of range for a long. But if you don't do the unnecessary .longValue() calls , the code works:
BigInteger iter = BigInteger.valueOf(140);
BigInteger y = BigInteger.valueOf(1114112);
BigInteger sum = BigInteger.valueOf(0);
while(iter.intValue() != 0) {
BigInteger z = y.pow(iter.intValue();
sum = sum.add(z);
iter = iter.subtract(BigInteger.valueOf(1));
System.out.println("Itereration: " + (140 - iter.longValue()));
System.out.println("Y: " + y);
System.out.println("Z: " + z);
System.out.println("Sum: " + sum);
}
And as #RC. has suggested in the comment, you could make iter a simple int, which simplifies the code further:
int iter = 140;
BigInteger y = BigInteger.valueOf(1114112);
BigInteger sum = BigInteger.valueOf(0);
while(iter != 0) {
BigInteger z = y.pow(iter);
sum = sum.add(z);
iter--;
System.out.println("Itereration: " + (140 - iter));
System.out.println("Y: " + y);
System.out.println("Z: " + z);
System.out.println("Sum: " + sum);
}

Modify solution to use a single loop

I managed to solve this, below is my solution :
public class ProblemA001k {
public static void main(String[] args) {
System.out.println("Sum from 1" + " to " + divQ + ":" + sum2);
System.out.println();
divQ += q;
newQ += q;
sum1 = 0;
sum2 = 0;
}
key.close();
}
}
Now I was told to modify my solution so that it uses ONLY ONE LOOP.
I have 3 loops in the code above, even when I tried using only 2 loops I struggled. but ONE LOOP ? I don't know how to improve my code. Please help me.
This is a Mathematic problem.
If you know that you can find the sum of all integers from 1 to X, you just need to do X * (X+1) / 2.
You can find all the batch values easily.
Sum from 1 to 400: 80200
Sum from 401 to 450: 21275
Sum from 1 to 450: 101475
Will be found like this :
450 * 451 / 2 = 101475 (1 to 450)
400 * 401 / 2 = 80200 (1 to 400)
101475 - 80200 = 21275 (401 to 450)
With this, you can limit the loop to just calculate the values from q to n by incrementing by q
And a quick code to do it :
static void sum(int n, int q){
int i = q;
int sum, tmp=0;
while(i < n){
sum = i * (i+1) / 2;
System.out.println(String.format("Sum from %d to %d : %d", i-q+1 , i, sum - tmp));
System.out.println(String.format("Sum from %d to %d : %d", 1, i, sum));
tmp = sum;
i += q;
}
}
And I run it with
public static void main(String[] args){
sum(500, 50);
}
to have this result
Sum from 1 to 50 : 1275
Sum from 1 to 50 : 1275
Sum from 51 to 100 : 3775
Sum from 1 to 100 : 5050
Sum from 101 to 150 : 6275
Sum from 1 to 150 : 11325
Sum from 151 to 200 : 8775
Sum from 1 to 200 : 20100
Sum from 201 to 250 : 11275
Sum from 1 to 250 : 31375
Sum from 251 to 300 : 13775
Sum from 1 to 300 : 45150
Sum from 301 to 350 : 16275
Sum from 1 to 350 : 61425
Sum from 351 to 400 : 18775
Sum from 1 to 400 : 80200
Sum from 401 to 450 : 21275
Sum from 1 to 450 : 101475
The good think with this solution is the number of loop, this will increment by q instead of 1
Note : The solution is a quick implementation, this could be done better.
EDIT :
Thanks to Margaret Bloom in the comments to point out the name of this formula :) For more information, you are welcome to look at Triangular Number
This should do it:
int totalSum = 0;
int batchSum = 0;
for (int i = 1; i <= n; i++) {
totalSum += i;
batchSum += i;
if (i % q == 0) {
System.out.println("Sum from " + (i - q + 1) + " to " + i + ":" + batchSum);
System.out.println("Sum from 1 to " + i + ":" + totalSum);
batchSum = 0;
}
}
Edit:
The better Math way:
int lastTotalSum = 0;
for (int i = 1; i <= n / q; i++ ) {
int top = i * q;
int totalSum = top * (top + 1) / 2;
int batchSum = totalSum - lastTotalSum;
System.out.println("Sum from " + (top - q + 1) + " to " + top + ":" + batchSum);
System.out.println("Sum from 1 to " + top + ":" + totalSum);
lastTotalSum = totalSum;
}
I found a nice solution with java8 Streams:
int n=1000;
int q=50;
int length = n/q -1;
int[] previousSum={0};
IntStream.range(0, length).map(i -> (i+1)*q).forEach(s -> {
int sum=(s*(s+1))/2;
int batch = sum - previousSum[0];
previousSum[0] = sum;
System.out.println("Sum from " + (s - q + 1) + " to " + s + ":" + batch);
System.out.println("Sum from 1 to " + s + ":" + sum);
});
Do one loop iterating entire range and use indexes to decide whether to add, reset or print your sums.
Hope this gives your right idea, if you still dont know I can illustrate it a bit more.

Counting number of comparisons in code

for(int i = 0; i < N * N; i = i + 1)
for(int j = 1; j < i + 1; j = j + 1)
junk = junk + 1;
I need to determine the relationship between the number of < operations executed and N. I should give an exact answer, such as 27N + 18.
Any help is appreciated! Thanks
For the first loop, as you can see i starts from 0 and goes to N^2 -1
1) That means N^2 + 1 times.
For every i, inner loop starts with 1 goes to N^2
2) 1 + 2 + 3 ... (N^2) = N^2 * (N^2 +1 ) / 2 = (N^4 + N^2) / 2
That means, operator "<" executed sum of 1 and 2.
N^2 + 1 + (N^4 + N^2) / 2 = (N^4 + 3N^2 + 2) / 2
= **(N^2 + 2) (N^2 + 1) / 2**

Java Recursion method

The below method return 5 if you give n = 20.
My question is how is 1 incremented on each iteration?
mystery(10) + 1
= mystery(5) + 2
= mystery(2) + 3
= mystery(1) + 4
= mystery(0) + 5 = 5.
I am having some hard time with recursion.
public static int mystery(int n){
if(n <= 0){
return 0;
}else{
return mystery(n / 2 ) + 1;
}
}
mystery(20) = mystery(10) + 1
mystery(20) = (mystery(5) + 1) + 1
mystery(20) = ((mystery(2) + 1) + 1) + 1
mystery(20) = (((mystery(1) + 1) + 1) + 1) + 1
mystery(20) = ((((mystery(0) + 1) + 1) + 1) + 1) + 1
and we know that mystery(0) = 0.
mystery(20) = ((((0 + 1) + 1) + 1) + 1) + 1
mystery(20) = (((1 + 1) + 1) + 1) + 1
mystery(20) = ((2 + 1) + 1) + 1
mystery(20) = (3 + 1) + 1
mystery(20) = 4 + 1
mystery(20) = 5
Or, simply put, we get 1+1+1+1+1=5
Pretty good video on recursion here: https://www.youtube.com/watch?v=Mv9NEXX1VHc
Looking at the code should make it obvious that:
mystery(20) = mystery(10) + 1
mystery(10) = mystery(5) + 1
mystery(5) = mystery(2) + 1
mystery(2) = mystery(1) + 1
mystery(1) = mystery(0) + 1
mystery(0) = 0
Now go back and plug in all the values, e.g.
mystery(1) = mystery(0) + 1 = 0 + 1 = 1
mystery(2) = mystery(1) + 1 = 1 + 1 = 2
mystery(5) = mystery(2) + 1 = 2 + 1 = 3, etc.
Every time mystery() is called, it returns the value returned by calling itself, plus 1. So, for every call, the returned number gets incremented by 1.

Categories

Resources