Recursive function to iterative function as binoms - java

I'm new with algorithms and wonder how this displayed function is supposed to be converted/transformed from recursive to iterative. What should I keep in mind when converting?
public int binom(int n, int k)
{
if (k == 0 || n == k) { return 1; }
return binom(n - 1, k - 1) + binom(n - 1, k);
}
Thanks in advance!

In fact, this problem is not so easy, if you just look at the recursive code and try to decrypt it.
However, it might be a helpful hint for you, that (n over k), i.e. the binomial coefficient can be written as
n! / (k! * (n - k)!)
where "!" denotes the factorial.
And it should be rather easy to compute the factorial in a Loop (i.e. iterative) for you.
If intermediate results are too big you can shorten before computation. You can shorten either term k! or the term (n-k)! (you would choose the bigger one). For example with n = 5 and k = 3 you have:
(1 * 2 * 3 * 4 * 5) / ((1 * 2 * 3) * (1 * 2)) = (4 * 5) / (1 * 2)
Spoiler-Alarm:
public static int binomial(int n, int k) {
int nMinusK = n - k;
if (n < nMinusK) {
//Switch n and nMinusK
int temp = n;
n = nMinusK;
nMinusK = temp;
}
int result = 1;
// n!/k!
for (int i = k + 1; i <= n; i++) {
result *= i;
}
//Division by (n-k)!
for (int j = 1; j <= nMinusK; j++) {
result = result / j;
}
return result;
}

You can use the multiplicative form of binomial coefficients, for example from Wikia, which can be easily implemented with faculties or loops.

Related

Time Complexity Improvement for Project Euler Solution

This is my solution to the first question in Project Euler.
Could someone please help reduce the time complexity of this working code?
Problem:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
public class Sum {
private static final int n = 1000;
public static void main(String[] args) {
for (int i = 1, sum = 0; i <= n; i++) {
if ((i % 3 == 0) || (i % 5 == 0)) {
System.out.println(sum += i);
}
}
}
}
I am using the formula provided by phatfingers.
You can have numbers that are divisible by 15 (3 * 5), so you kinda have to subtract that amount.
Because the formula without k works for all natural numbers up to n, you multiply the thing by k. But this expands your scale by a factor of k, so I divided n by k (automatically being rounded down).
public class Sum {
private static final int n = 15;
public static void main(String[] args) {
int result = compute(3, n) + compute(5, n) - compute(15, n);
System.out.println(result);
}
private static int compute(int k, int n) {
n = n / k;
return k * n * (n + 1) / 2;
}
}
Note:
You can declare your variables inside of the for-loop
You check i < n (n exclusive) instead of i <= n (n inclusive, which I think you want here). If you don't want this, change n = n / k to n = (n - 1) / k.

Number of ways to form a mountain ranges

I am looking at an application of catalan numbers:
Number of ways to form a “mountain ranges” with n upstrokes and n down-strokes that all stay above the original line.
Now given a number n, find the number of mountain ranges.
public int countMountainRanges(int n) {
}
What logic or formula can we use here to get the number of ways for input n.
I tried the formula F(n) = F(n-1) + F(n-2), but it does not work in this case.
F(n) = F(n-1) + F(n-2) is the formula for the nth Fibonacci number. The nth Catalan number, on the other hand, is given by (2n choose n) / (n + 1).
public static int countMountainRanges(int n) {
return choose(2 * n , n) / (n + 1);
}
private static int choose(int n, int k){
int res = 1;
k = Math.min(k, n - k);
for (int i = 0; i < k; i++) {
res = res * (n - i) / (i + 1);
}
return res;
}

Explain the implementation of Euler's Totient Implementation

I have seen this code in a coding platform to efficiently calculate the euler's totient for different values.
I am not being able to understand this implementation. I really want to learn this. Could anyone please help me explain this?
for(int i = 1; i < Maxn; i++) { // phi[1....n] in n * log(n)
phi[i] += i;
for(int j = 2 * i; j < Maxn; j += i) {
phi[j] -= phi[i];
}
}
First, lets note that for prime values p, phi(p) = p - 1. This should be fairly intuitive, because all numbers less than a prime must be coprime to said prime. So then we start into our outer for loop:
for(int i = 1; i < Maxn; i++) { // phi[1....n] in n * log(n)
phi[i] += i;
Here we add the value of i to phi(i). For the prime case, this means we need phi(i) to equal -1 beforehand, and all other phi(i) must be adjusted further to account for the number of coprime integers. Focusing on the prime case, lets convince ourselves that these do equal -1.
If we step through the loop, at case i=1, we'll end up iterating over all other elements in our inner loop, subtracting 1.
for(int j = 2 * i; j < Maxn; j += i) {
phi[j] -= phi[i];
}
For any other values to be subtracted j must equal the prime p. But that would require j = 2 * i + i * k to equal p, for some iteration k. That cannot be, because 2 * i + i * k == i * (2 + k) implying that p can be divided evenly by i, which it cannot (since its prime). Thus, all phi(p) = p - 1.
For non-prime i, we need to subtract out the number of coprime integers. We do this in the inner for loop. Reusing the formula from before, if i divides j, we get j / i = (2 + k). So every value less than i can be multiplied by (2 + k) to be less than j, yet have a common factor of (2 + k) with j (thus, not coprime).
However, if we subtracted out (i - 1) multiples containing (2 + k) factors, we'd count the same factors multiple times. Instead, we only count those which are coprime to i, or in other words phi(i). Thus, we are left with phi(x) = x - phi(factor_a) - phi(factor_b) ... to account for all the (2 + k_factor) multiples of coprimes less than said factor, which now share a factor of (2 + k_factor) with x.
Putting this into code gives us exactly what you have above:
for(int i = 1; i < Maxn; i++) { // phi[1....n] in n * log(n)
phi[i] += i;
for(int j = 2 * i; j < Maxn; j += i) {
phi[j] -= phi[i];
}
}
By the way, just out of interest, there's also an O(n) algorithm to achieve the same. We know Euler's product formula for the totient is
phi(n) = n * product(
(p - 1) / p)
where p is a distinct prime that divide n
For example,
phi(18) = 18 * (
(2-1)/2 * (3-1)/3)
= 18 * 2/6
= 18 * 1/3
= 6
Now consider a number m = n * p for some prime p.
phi(n) = n * product(
(p' - 1) / p')
where p' is a distinct prime that divide n
If p divides n, since p already appears in the calculation for phi(n), we do not need to add it to the product section, rather we just add it to the initial multiplier
phi(m) = phi(p * n) = p * n * product(
(p' - 1) / p')
= p * phi(n)
Otherwise, if p does not divide n, we need to use the new prime,
phi(m) = phi(p * n) = p * n * product(
(p' - 1) / p') * (p - 1) / p
= p * (p - 1) / p * n * product(
(p' - 1) / p')
= (p - 1) * phi(n)
Either way, we can calculate the totient of a number multiplied by a prime only from the prime and the number's own totient, which can be aggregated in O(n) by repeatedly multiplying the numbers we've generated so far by the next prime we find until we reach Maxn. We find the next prime by incrementing an index to the successor we haven't recorded a totient for (prime generation here is a benefit).

Represent an Integer as a sum of Consecutive positive integers

I am writing code for counting the number of ways an integer can be represented as a sum of the consecutive integers. For Example
15=(7+8),(1+2+3+4+5),(4+5+6). So the number of ways equals 3 for 15.
Now the input size can be <=10^12. My program is working fine till 10^7(i think so, but not sure as i didnt check it on any online judge. Feel free to check the code for that)
but as soon as the i give it 10^8 or higher integer as input. it throws many runtime exceptions(it doesnt show what runtime error). Thanks in advance.
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
Use some math: if arithmetic progression with difference 1 starts with a0 and contains n items, then its sum is
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
note that the second summand rises as quadratic function. So instead of checking all a0 in range S/2, we can check all n is smaller range
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(I used some higher approximation).
Just test whether next expression gives integer positive result
a0 = (S - n * (n - 1) / 2) / n
Recursive function isn't suitable when you have big input size like your case.
The maximum depth of the java call stack is about 8900 calls and sometimes only after 7700 calls stack overflow occurs so it really depends on your program input size.
Try this algorithm I think it worked for your problem:
it will work fine until 10^9 after that it will take much more time to finish running the program.
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
Output:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
There's a really excellent proof that the answer can be determined by solving for the unique odd factors (Reference). Essentially, for every odd factor of a target value, there exists either an odd series of numbers of that factor multiplied by its average to produce the target value, or an odd average equal to that factor that can be multiplied by double an even-sized series to reach the target value.
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
As #MBo noted, if a number S can be partitioned into n consecutive parts, then S - T(n) must be divisible by n, where T(n) is the n'th triangular number, and so you can count the number of partitions in O(sqrt(S)) time.
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
A bit more math yields an even simpler way. Wikipedia says:
The politeness of a positive number is defined as the number of ways it can be expressed as the sum of consecutive integers. For every x, the politeness of x equals the number of odd divisors of x that are greater than one.
Also see: OEIS A069283
So a simple solution with lots of room for optimization is:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}

Maximum value of int breaking my for loop?

I was attempting to solve this morning's Codeforces problem Div 2C: http://codeforces.com/contest/716/problem/C
This problem has the potential to loop up to 100,000 times so the parameter here can be up to 100,000. Loop seems to break when passing in 100,000 (and possibly earlier) and i is declared as an int:
public void solve(int a) {
double x = 2;
double y = 0;
double n = 0;
double target = 0;
double lcm = 0;
for (int i = 1; i <= a; i++) {
lcm = (i + 1) * i;
y = ((lcm * lcm) - x) / i;
n = (y * i) + x;
if (Math.sqrt(n) % (i + 1) == 0) {
x = Math.sqrt(n);
String answer = String.format("%.0f", y);
System.out.println("this is i: " + i);
System.out.println(answer);
}
}
}
Here is the relevant output:
this is i: 46337
99495281029892
this is i: 46338
99501722706961
this is i: 46340
99514606895203
this is i: 65535
32769
Doing a quick search on Stack overflow shows that the number 65535 is associated with a 16-bit unsigned int, but java uses 32bit ints. Changing the type to double works, as does simply looping 100,000 times and printing without the code logic. I understand that 100,000^2 IS above the maximum int limit, but this value is never stored as an int in my code. What's going on here?
The following line generates an out of bounds int before converting the result to double:
lcm = (i + 1) * i;
The above is essentially the same as:
lcm = (double)((i + 1) * i);
or
int temp = (i + 1) * i;
lcm = (double) temp;
Instead try (first converting to double and then taking what is similar to a square):
lcm = (i + 1.0) * i;

Categories

Resources