Closed expression, in terms of n - java

I have been trying to derive an expression in terms of n for the following. The closest I have been by the result is with log_2(n), (base 2). Thank you :)
public static int v(int n) {
int r = 0;
for(int i=1;i<n;i*=2) {
r=r+1;
}
return r;
}

Is this good enough for you:
public static int v2(int n) {
if(n <= 1)
return 0;
return (int) (Math.log(n - 1) / Math.log(2)) + 1;
}
In other words log_2(n-1)+1 for n > 1 and 0 otherwise.

Related

Stackoverflow Error in Staircase Problem when step size is greater than 3

I'm trying to solve the staircase problem in java with a method that gets the number of stairs (n) and the maximum step size (maxStep). Somehow it works until step size is > 3 after that I get a Stackoverflow error but I don't know why that is.
public static int climbStairs(int n, int maxStep) {
if (n == 0 || n == 1) {
return 1;
} else if (n == 2) {
return 2;
} else {
int count = 0;
for (int i = 1; i <= maxStep; i++) {
count += climbStairs(n - i, maxStep);
}
return count;
}
}
Try this code hope it will work.
public static int climbStairs2(int n, int maxStep) {
if (n == 0 || n == 1) {
return 1;
} else if (n < maxStep) {
return n;
} else {
int count = 0;
for (int i = 1; i <= maxStep; i++) {
count += climbStairs2(n - i, maxStep);
}
return count;
}
}
You don't check whether the maxstep is smaller than the step count. This means that after a while, the i<=maxstep can be > n, which results in negative n for the next recursion. If it once turns to the negatives, it will recurse infinitely. To fix it, just check for n<=maxstep or n<=0.
Example of your 'bad' code: Try inputs 5,4: it will start the method with n=
5
4
3
-1
-2

Count number of Divisors for all the numbers till N

I need to count all the divisors for every number in the range 1 to n. I have written down below an implementation for, given an integer num, it counts the number of divisors of num. Its complexity is O(sqrt(n)). So over all complexity comes out to be O(n * sqrt(n)). Can it be reduced? If YES, then can you give an algorithm for that?
CODE :
public static int countDivisors(int num)
{
int limit = (int)Math.sqrt(num);
int count = 2;
for(int i = 2 ; i <= limit ; i++)
{
if(num % i == 0)
{
count++;
if(num / i != i)
{
count++;
}
}
}
return count;
}
PS:
This function will be called n times.
You can improve upon the naive approach using kind of a generalized Sieve of Eratosthenes. Instead of just marking the number as composite also store its first divisor that you found (I do this in the function computeDivs below).
class Main
{
// using Sieve of Eratosthenes to factorize all numbers
public static int[] computeDivs(int size) {
int[] divs = new int[size + 1];
for (int i = 0; i < size + 1; ++i) {
divs[i] = 1;
}
int o = (int)Math.sqrt((double)size);
for (int i = 2; i <= size; i += 2) {
divs[i] = 2;
}
for (int i = 3; i <= size; i += 2) {
if (divs[i] != 1) {
continue;
}
divs[i] = i;
if (i <= o) {
for (int j = i * i; j < size; j += 2 * i) {
divs[j] = i;
}
}
}
return divs;
}
// Counting the divisors using the standard fomula
public static int countDivisors(int x, int[] divs) {
int result = 1;
int currentDivisor = divs[x];
int currentCount = 1;
while (currentDivisor != 1) {
x /= currentDivisor;
int newDivisor = divs[x];
if (newDivisor != currentDivisor) {
result *= currentCount + 1;
currentDivisor = newDivisor;
currentCount = 1;
} else {
currentCount++;
}
}
if (x != 1) {
result *= currentCount + 1;
}
return result;
}
public static int countAllDivisors(int upTo) {
int[] divs = computeDivs(upTo + 1);
int result = 0;
for (int i = 1; i <= upTo; ++i) {
result += countDivisors(i, divs);
}
return result;
}
public static void main (String[] args) throws java.lang.Exception {
System.out.println(countAllDivisors(15));
}
}
You can also see the code executed on ideone here.
In short I use the sieve to compute the biggest prime factor for each number. Using this I can compute the factor decomposition of every number very efficiently (and I use this in countDivisors).
It is hard to compute the complexity of the sieve but a standard estimate is O(n * log(n)). Also I am pretty confident it is not possible to improve on that complexity.
You can do much better than O(n.sqrt(n)) by using simple iteration. The code is in C++, but you can easily get the idea.
#include <iostream>
#include <vector>
using namespace std;
void CountDivisors(int n) {
vector<int> cnts(n + 1, 1);
for (int i = 2; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
cnts[j]++;
}
}
for (int i = 1; i <= n; ++i) {
cout << cnts[i] << " \n"[i == n];
}
}
int main() {
CountDivisors(100);
return 0;
}
Running time is n/1 + n/2 + n/3 + n/4 + ... + n/n which can be approximated by O(nH(n)), where H(n) is the harmonic series. I think the value is not bigger than O(nlog(n)).
Using iteration is OK for relatively small numbers. As soon as the number of divisors is getting bigger (over 100-200), the iteration is going to take a significant amount of time.
A better approach would be to count the number of divisors with help of prime factorization of the number.
So, express the number with prime factorization like this:
public static List<Integer> primeFactorizationOfTheNumber(long number) {
List<Integer> primes = new ArrayList<>();
var remainder = number;
var prime = 2;
while (remainder != 1) {
if (remainder % prime == 0) {
primes.add(prime);
remainder = remainder / prime;
} else {
prime++;
}
}
return primes;
}
Next, given the prime factorization, express it in the exponent form, get exponents and add 1 to each of them. Next, multiply resulting numbers. The result will be the count of divisors of a number. More on this here.
private long numberOfDivisorsForNumber(long number) {
var exponentsOfPrimeFactorization = primeFactorizationOfTheNumber(number)
.stream()
.collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()))
.values();
return exponentsOfPrimeFactorization.stream().map(n -> n + 1).reduce(1L, Math::multiplyExact);
}
This algorithm works very fast. For me, it finds a number with 500 divisors within less than a second.

difficulty with fibonacci function

I'm supposed to change this recursive function, into an iterative function...
int rFib(int n)
{ //assumes n >= 0
if(n <= 1)
return n;
else
return (rFib(n-1) + rFib(n-2));
}
But I'm drawing a blank on the mathematical view of this... I would appreciate any assistance. I was able to get the other 3 functions, but I just can't seem to figure out the math of this one.
public static int fib(int n)
{
int theFib = 1;
while(n > 1)
{
theFib = n - 1;
n = n + n - 2;
}
System.out.println(theFib);
return theFib;
}
The next number in the Fibonacci sequence is the sum of the last two numbers, so you'll need to remember the last two numbers.
In pseudo code, since you should do some of the homework yourself:
n1 = 0
n2 = 1
loop
n = n1 + n2
n1 = n2
n2 = n
end loop
I'll leave it to you to limit the looping.
You can find an example here.
The code in question:
public class FibonacciIterative {
public static int fib(int n) {
int prev1=0, prev2=1;
for(int i=0; i<n; i++) {
int savePrev1 = prev1;
prev1 = prev2;
prev2 = savePrev1 + prev2;
}
return prev1;
}
}
It does not really matter which direction (up or down) you count. The challenge is to deal with the limits properly.
Using dynamic programming technique:
static int fib(int n) {
int[] fibs = new int[n + 1];
for (int i = 0; i <= n; i++) {
if (i <= 1) {
fibs[i] = i;
} else {
fibs[i] = fibs[i - 1] + fibs[i - 2];
}
}
return fibs[n];
}

Extracting even digits from int

Here is the problem that I am solving.
Write a method evenDigits that accepts an integer parameter n and that
returns the integer formed by removing the odd digits from n. The
following table shows several calls and their expected return values:
Call Valued Returned
evenDigits(8342116); 8426
evenDigits(4109); 40
evenDigits(8); 8
evenDigits(-34512); -42
evenDigits(-163505); -60
evenDigits(3052); 2
evenDigits(7010496); 46
evenDigits(35179); 0
evenDigits(5307); 0
evenDigits(7); 0
If a negative number with even digits other than 0 is passed to the method, the result should also be negative, as shown above when -34512 is passed.
Leading zeros in the result should be ignored and if there are no even digits other than 0 in the number, the method should return 0, as shown in the last three outputs.
I have this so far -
public static int evenDigits(int n) {
    if (n != 0) { 
        int new_x = 0;
int temp = 0;
String subS = "";
    String x_str = Integer.toString(n);
if (x_str.substring(0, 1).equals("-")) {
 temp = Integer.parseInt(x_str.substring(0, 2));
 subS = x_str.substring(2);
} else {
 temp = Integer.parseInt(x_str.substring(0, 1));
 subS = x_str.substring(1);
}
        if (subS.length() != 0) {
             new_x = Integer.parseInt(x_str.substring(1));
        }
        
        if (temp % 2 == 0) {
             return Integer.parseInt((Integer.toString(temp) + evenDigits(new_x)));
        } else {
            return evenDigits(new_x);
        }
    }
return 0;
}
Why do people seem always to want to convert to String to deal with digits? Java has perfectly good arithmetic primitives for handling the job. For example:
public static int evenDigits(int n) {
int rev = 0;
int digitCount = 0;
// handle negative arguments
if (n < 0) return -evenDigits(-n);
// Extract the even digits to variable rev
while (n != 0) {
if (n % 2 == 0) {
rev = rev * 10 + n % 10;
digitCount += 1;
}
n /= 10;
}
// The digits were extracted in reverse order; reverse them again
while (digitCount > 0) {
n = n * 10 + rev % 10;
rev /= 10;
digitCount -= 1;
}
// The result is in n
return n;
}
Although it makes no difference for a simple academic exercise such as this one, handling the job via arithmetic alone can be expected to perform better than anything involving converting to String.
It's often easier to start with a recursive solution and then work you way back to iterative (if you must):
public static int evenDigits(int n) {
if (n < 0) {
return -evenDigits(-n);
} else if (n == 0) {
return 0;
} else if (n % 2 == 1) {
return evenDigits(n / 10);
} else {
return 10 * evenDigits(n / 10) + (n % 10);
}
}
int n = 8342116;
StringBuilder sb = new StringBuilder();
Integer.toString(n).chars()
.filter(x -> x % 2 == 0)
.mapToObj(i -> (char) i)
.forEachOrdered(sb::append);
int result = Integer.valueOf(sb.toString());
System.out.println(result); // 8426
public int evenDigits(int n) {
int r = 0;
boolean neg = false;
String evenDigits = "";
if (n < 0) { neg = true; n = abs(n); }
// keep dividing n until n = 0
while (n > 0) {
r = n % 10;
n = n / 10; // int division
if (r % 2 == 0) { evenDigits = Integer.toString(r) + evenDigits; }
}
int result = Integer.parseInt(evenDigits);
if (neg) { result -= 2 * result; }
return result;
}
This is more or less a pseudo code, but I think you get my idea. I have used this method for the same problem before.
A layman's solution that's based on Strings:
public static int evenDigits(int n) {
StringBuilder evenDigitsBuffer = new StringBuilder();
for (char digitChar : String.valueOf(n).toCharArray()) {
int digit = Character.getNumericValue(digitChar);
if (digit % 2 == 0) {
evenDigitsBuffer.append(digit);
}
}
return evenDigitsBuffer.length() > 0
? Integer.signum(n) * Integer.parseInt(evenDigitsBuffer.toString())
: 0;
}

Sum of Powers of two Integers using only For-Loops

The question here would be to get the sum of powers (m^0 + m^1 + m^2 + m^3.... + m^n) using only FOR loops. Meaning, not using any other loops as well as Math.pow();
Is it even possible? So far, I am only able to work around getting m^n, but not the rest.
public static void main(String[] args){
Scanner scn = new Scanner(System.in);
int total = 1;
System.out.print("Enter value of m: ");
int m = scn.nextInt();
System.out.print("Enter value of n: ");
int n = scn.nextInt();
for (int i = 1; i <= n; i++){
total * m;
}
System.out.print(total);
}
Let's say m =8; and n = 4;
i gives me '1,2,3,4' which is what I need, but I am unable to power m ^ i.
Would be nice if someone could guide me into how it could be done, can't seem to progress onwards as I have limited knowledge in Java.
Thanks in advance!
You might want to rewrite it like this :
m^0 + m^1 + m^2 + m^3.... + m^n = 1 + m * (1 + m * (1 + m * (.... ) ) )
And you do it in a single for loop.
This should do the job (see explanations in comments):
public long count(long m, int pow) {
long result = 1;
for(int i = 0;i<pow; i++) {
result*=m +1;
}
return result;
}
You can nest loops. Use one to compute the powers and another to sum them.
You can do below:
int mul = 1;
total = 1;
for(int i=1;i<=n;i++) {
mul *= m;
total += mul;
}
System.out.println(total);
You can use a single loop which is O(N) instead of nested loops which is O(N^2)
long total = 1, power = m
for (int i = 1; i <= n; i++){
total += power;
power *= m;
}
System.out.print(total);
You can also use the formula for geometric series:
Sum[i = k..k+n](a^i) = (a^k - a^(k+n+1)) / (1 - a)
= a^k * (1 - a^(n+1)) / (1 - a)
With this, the implementation can be done in a single for loop (or 2 simple for loop): either with O(n) simple looping, or with O(log n) exponentiation by squaring.
However, the drawback is that the data type must be able to hold at least (1 - a^(n+1)), while summing up normally only requires the result to fit in the data type.
This is the solution :
for(int i=0;i<n;i++){
temp=1;
for(int j=0;j<=i;j++){
temp *= m;
}
total += temp;
}
System.out.println(total+1);
You can easily calculate powers using your own pow function, something like:
private static long power(int a, int b) {
if (b < 0) {
throw new UnsupportedOperationException("Negative powers not supported.");
}
if (b == 0) {
return 1;
}
if (b == 1) {
return a;
}
return a * power(a, b - 1);
}
Then simply loop over all the values and add them up:
long out = 0;
for (int i = 0; i <= n; ++i) {
out += power(m, i);
}
System.out.println(out);
I would add that this is a classic dynamic programming problem as m^n is m * m^(n-1). I would therefore add caching of previously calculated powers so that you don't have to recalculate.
private static Map<Integer, Long> powers;
public static void main(String args[]) {
int m = 4;
int n = 4;
powers = new HashMap<>();
long out = 0;
for (int i = 0; i <= n; ++i) {
out += power(m, i);
}
System.out.println(out);
System.out.println(powers);
}
private static long power(int a, int b) {
if (b < 0) {
throw new UnsupportedOperationException("Negative powers not supported.");
}
if (b == 0) {
return 1;
}
if (b == 1) {
return a;
}
Long power = powers.get(b);
if (power == null) {
power = a * power(a, b - 1);
powers.put(b, power);
}
return power;
}
This caches calculated values so that you only calculate the next multiple each time.

Categories

Resources