patternjavaModerate
Finding non-bouncy numbers under 10^x
Viewed 0 times
bouncynonnumbersunderfinding
Problem
I am trying to find non bouncy numbers under \$10^x\$ where \$1\le x\le 1000\$.
\$123456\$ is an increasing number where every digit is greater than or equal to the previous digit (\$1223344\$ is also counted as an increasing number).
Similarly a decreasing number is one where every digit is smaller than or equal to the previous digit (\$443322\$ is also counted as an decreasing number).
155224 such numbers, which are neither increasing, nor decreasing, are bouncy numbers, such that 12951 numbers below one-million that are not bouncy. I want to find number of non bouncy number under \$10^x\$.
My code works perfectly fine, but when \$n\$ is greater than 7, it takes way too much time to give the output! So, it needs performance optimizations.
\$123456\$ is an increasing number where every digit is greater than or equal to the previous digit (\$1223344\$ is also counted as an increasing number).
Similarly a decreasing number is one where every digit is smaller than or equal to the previous digit (\$443322\$ is also counted as an decreasing number).
155224 such numbers, which are neither increasing, nor decreasing, are bouncy numbers, such that 12951 numbers below one-million that are not bouncy. I want to find number of non bouncy number under \$10^x\$.
My code works perfectly fine, but when \$n\$ is greater than 7, it takes way too much time to give the output! So, it needs performance optimizations.
import java.util.*;
class A{
static String s;
public static void main(String z[]){
int n,i;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
int input[]=new int[n];
int output[]=new int[n];
for(i=0;is.charAt(i+1)){
return false;
}
}
return true;
}
public static boolean isDecreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)<s.charAt(i+1)){
return false;
}
}
return true;
}
public static int noOfBouncy(int k){
int limit=(int)Math.pow(10,k);
int count=0;
int num=1;
while(num<limit){
s=new String(Integer.toString(num));
if(isIncreasing(s) || isDecreasing(s) ){
}
else{
count++;
}
num++;
}
count=limit-count;
return count-1;
}
}Solution
This is not a review but an expanded comment.
Brute force is bad. Do some math first.
Consider a non-decreasing number of length \$n\$ formed by exactly \$k\$ given digits. It has exactly \$k - 1\$ transitions from a digit to a larger one, and there are exactly \$n - 1\$ places where the transition may happen, so there are \$\binom{n-1}{k-1}\$ such numbers. The \$\binom{10}{k}\$ ways to pick \$k\$ digits give a subtotal of \$\binom{n-1}{k-1}\binom{10}{k}\$, and a grand total is \$\sum_{k=1}^{10}\binom{n-1}{k-1}\binom{10}{k}\$.
So the problem nails down to efficient calculation of binomial coefficients, which in this case is fairly straightforward, since you never need more than 10 factors.
Brute force is bad. Do some math first.
Consider a non-decreasing number of length \$n\$ formed by exactly \$k\$ given digits. It has exactly \$k - 1\$ transitions from a digit to a larger one, and there are exactly \$n - 1\$ places where the transition may happen, so there are \$\binom{n-1}{k-1}\$ such numbers. The \$\binom{10}{k}\$ ways to pick \$k\$ digits give a subtotal of \$\binom{n-1}{k-1}\binom{10}{k}\$, and a grand total is \$\sum_{k=1}^{10}\binom{n-1}{k-1}\binom{10}{k}\$.
So the problem nails down to efficient calculation of binomial coefficients, which in this case is fairly straightforward, since you never need more than 10 factors.
Context
StackExchange Code Review Q#110450, answer score: 11
Revisions (0)
No revisions yet.