Trailing Zeroes of a Factorial - java

I'm trying to solve this coding question:
Given an integer n, return the number of trailing zeroes in n!
Below is my code (codec this up using the wiki link)
public int trailingZeroes(int n) {
int count = 0, i = 5;
while(i<=n){
count+= n/i;
i*=5;
}
return count;
}
This runs for all test cases except when n = Integer.MAX_VALUE upon which I get a TLE. How can I fix this code to make it cover that test case. I have read about five articles on the net and everything seems to agree with my approach.
Much thanks.
So, I followed the long/BigInteger approach (thanks y'all):
public int trailingZeroes(int n) {
long count = 0;
for(long i= 5; n/i >= 1; i= i*5){
count+= n/i;
}
return (int)count;
}

As Iaune observed, your loop will never terminate when n is Integer.MAX_VALUE, because there is no int greater than that number (by definition). You should be able to restructure your loop to avoid that problem. For instance, this is the same basic approach, but flipped upside-down:
public int trailingZeroes(int n) {
int count = 0;
while (n > 0) {
n /= 5;
count += n;
}
return count;
}

You cannot write a for or while loop where the loop counter is an int and the upper limit is <= Integer.MAX_VALUE.
What happens with a simple increment (counter++) is that the loop counter is set to that value, the body executes and then the counter is incremented which results in a negative number, Integer.MIN_VALUE. And then everything happens all over again.
Other weird things may happen when the loop counter is incremented in quantities > 1 or (as here) is multiplied: the int loop counter just can't hold a value > Integer.MAX_VALUE
Consider another approach for iterating over these numbers. Or handle MAX_VALUE separately.

Your problem is that once i gets large enough (more than Integer.MAX_INT / 5) then the line i*=5; causes i to overflow to the "wrong" value. The value in question is 5 to the 14th power, which is 6103515625, but which overflows to 1808548329.
The result of this is that the loop just keeps executing forever. i will never become a value that's not <= Integer.MAX_INT, because there's just no such int.
To avoid this, you need i to be a larger data type than an int. If you change i and count in your original code to long, this will work fine. Of course, BigInteger would also work.

public class FactorialNumberTrailingZeros {
public static void main(String[] args) {
System.out.println(trailingZeroes(1000020));
}
private static int trailingZeroes(int n) {
int count = 0;
while (n > 0 && (n % 10 == 0)) {
n /= 10;
count ++;
}
return count;
}
}

public static void main(String[] args) {
int result = findFactorialTrailingZero(100);
System.out.println("no of trailing zeros are " + result);
}
public static int findFactorialTrailingZero(int no) {
int zeros = no / 5;
int zeroIncrementNo = 25;
int zerosIncrementFactor = 1;
int nextZeroIncrenent = 5;
for (int i = 1;no >= zeroIncrementNo; i++) {
zeros=zeros+zerosIncrementFactor;
zeroIncrementNo=25*(i+1);
if(i+1==nextZeroIncrenent){
zerosIncrementFactor++;
nextZeroIncrenent=nextZeroIncrenent*5;
}
}
return zeros;

/*
[n/5]+[n/25]+[n/125]+....
if n<25 then [n/5]
if n<125 then [n/5]+[n/25]
if n<625 then [n/5]+[n/25]+[n/125]
*/
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int countTrailingZeroes(int n)
{
int res=0;
for(int i=5;i<=n;i=i*5){
res=res+n/i;
}
return res;
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n;
cin>>n;
cout<<countTrailingZeroes(n);
return 0;
}
Output
25
6
Explanation:
25!=1.551121e+25 i.e contains 6 trailing zeroes

Here is my python code that could solve your problem:
def check(n):
j,ans=5,0
while j<=n:
ans=ans+n//j
j=j*5
return ans

Related

Rounding integers to one significant digit

I want to round down an int in Java, what i mean is, if I have an int 45678, i want to convert that int into 40000
this is how im calling it
int den = placeValue(startCode,length);
and this is the code
static int placeValue(int N, int num)
{
int total = 1, value = 0, rem = 0;
while (true) {
rem = N % 10;
N = N / 10;
if (rem == num) {
value = total * rem;
break;
}
total = total * 10;
}
return value;
}
so if i have 89765, i would want 80000,
but instead it return the place value of whatever length is.
So,
for 89765, the length would be 5, so the return value is 5 i.e. the value in the ones place.
but if the number was 85760
then it would return 5000.
I hope that makes sense.
Any suggestions would be much appreicated.
In my opinions, if I can avoid 'calculating' I will compute the answer from other concept since I am not confidence on my math (haha).
Here is my answer. (only work in positive numbers)
I think the length of the inputted number is not necessary.
static int placeValue2(int N) {
String tar = N+"";
String rtn = tar.substring(0,1); // take first digital
for (int i=0;i<tar.length()-1;i++) // pad following digitals
rtn+="0";
return Integer.parseInt(rtn);
}
I appreciate you asked the question here.
Here is my solution. I don't know why you are taking two parameters, but I tried it from one param.
class PlaceValue{
int placeValue(int num){
int length = 0; int temp2=1;
boolean result=false;
long temp1=1;
if (num<0){
result=true;
num=num*(-1);
}
if (num==0){
System.out.println("Value 0 not allowed");
return 0;
}
while (temp1 <= num){ //This loop checks for the length, multiplying temp1 with 10
//untill its <= number. length++ counts the length.
length++;
temp1*=10;
}
for (int i=1; i<length; i++){//this loop multiplies temp2 with 10 length number times.
// like if length 2 then 100. if 5 then 10000
temp2=temp2*10;
}
temp2=(num/temp2)*temp2;
/* Let's say number is 2345. This would divide it over 1000, giving us 2;
in the same line multiplying it with the temp2 which is same 1000 resulting 2000.
now 2345 became 2000;
*/
if (result==true){
temp2=temp2*(-1);
}
return temp2;
}
}
Here is the code above. You can try this. If you are dealing with the long numbers, go for long in function type as well as the variable being returned and in the main function. I hope you understand. otherwise, ask me.
Do you want something like this?
public static int roundDown(int number, int magnitude) {
int mag = (int) Math.pow(10, magnitude);
return (number / mag) * mag;
}
roundDown(53278,4) -> 50000
roundDown(46287,3) -> 46000
roundDown(65478,2) -> 65400
roundDown(43298,1) -> 43290
roundDown(43278,0) -> 43278
So the equivalent that will only use the most significant digit is:
public static int roundDown(int number) {
int zeros = (int) Math.log10(number);
int mag = (int) Math.pow(10, zeros);
return (number / mag) * mag;
}

Program to sum the odd digits recursively

Using recursion, If n is 123, the code should return 4 (i.e. 1+3). But instead it is returning the last digit, in this case 3.
public static int sumOfOddDigits(NaturalNumber n) {
int ans = 0;
if (!n.isZero()) {
int r = n.divideBy10();
sumOfOddDigits(n);
if (r % 2 != 0) {
ans = ans + r;
}
n.multiplyBy10(r);
}
return ans;
}
It isn't clear what NaturalNumber is or why you would prefer it to int, but your algorithm is easy enough to follow with int (and off). First, you want the remainder (or modulus) of division by 10. That is the far right digit. Determine if it is odd. If it is add it to the answer, and then when you recurse divide by 10 and make sure to add the result to the answer. Like,
public static int sumOfOddDigits(int n) {
int ans = 0;
if (n != 0) {
int r = n % 10;
if (r % 2 != 0) {
ans += r;
}
ans += sumOfOddDigits(n / 10);
}
return ans;
}
One problem is that you’re calling multiplyBy on n and not doing anything with the result. NaturalNumber seems likely to be immutable, so the method call has no effect.
But using recursion lets you write declarative code, this kind of imperative logic isn’t needed. instead of mutating local variables you can use the argument list to hold the values to be used in the next iteration:
public static int sumOfOddDigits(final int n) {
return sumOfOddDigits(n, 0);
}
// overload to pass in running total as an argument
public static int sumOfOddDigits(final int n, final int total) {
// base case: no digits left
if (n == 0)
return total;
// n is even: check other digits of n
if (n % 2 == 0)
return sumOfOddDigits(n / 10, total);
// n is odd: add last digit to total,
// then check other digits of n
return sumOfOddDigits(n / 10, n % 10 + total);
}

Loop never starting

I am trying to write a small method which will calculate the exponent given a number and power (I know about math.pow I am just doing this for kicks). However the loop inside my method never starts and I cant figure out why. My code is below, all help appreciated.
public static void main(String[] args) {
int result = exponantCalculation(2, 3);
System.out.println(result);
}
public static int exponantCalculation(int number, int power) {
for (int i = 1;i >= power;i++) {
number = number * number;
}
return number;
}
You've used the wrong comparison operator in the loop condition (>=, should be <= or < — see other answers).
Not sure, maybe this was intentional, BUT if the method is meant to calculate "number to the power of power", then you're incorrectly squaring the result of the previous iteration. This will produce a much higher value that the number to the power of power.
You need to introduce a new variable and multiply it with number in the loop, e.g.
long result = 1;
for (int i = 0; i < power; i++) {
result *= number; // same as "result = result * number"
}
return result;
Minor note: I've intentionally used long type for the result, which can slightly defer the integer overflow problem for big values.
Condition inside for loop is wrong.
Since you are passing 3 as power in your method as parameter, i is initialized with 1 and then condition gets checked whether i>=power with is obviously not true in this case so your loop never starts.
Change
for (int i = 1;i >= power;i++)
to
for (int i = 1;i <= power;i++)
if you wish to calculate the power of any number, you can use following method
public static int exponantCalculation(int number, int power) {
int result = 1;
for (int i = 1;i <= power;i++) {
result = result * number;
}
return result;
}
The for loop condition was wrong, but also you need to sotre the result in another variable:
public static int exponantCalculation(int number, int power) {
if(power == 0){
return 1;
}
int result = 1;
for (int i = 1;i <= power;i++) {
result *= number;
}
return result;
}

Largest Divisor of N (Excluding Itself)

I'm trying to divide a list into sublists that are as large as possible. If the list can not be divided in such a way, I will handle it as needed, but I need get the largest number besides N itself that divides N evenly.
I wrote a really naive solution, but I feel like there should be maybe a formula or something to do this in constant time. My list are not that big, maximum size is 1000. This probably isn't the critical path, but is there a better algorithm?
public static int largestDivisor(int n){
int divisor = 0;
for (int i = 1; i <= n/2; i++)
if (n % i == 0)
divisor = i;
return divisor;
}
Iterate the values in reverse. Simply return the first one you find (it'll be the greatest). Something like,
public static int largestDivisor(int n) {
for (int i = n / 2; i >= 2; i--) {
if (n % i == 0) {
return i;
}
}
return 1;
}
Alternatively, you might make a slight improvement to #WillemVanOnsem's answer and start with odd values like;
public static int largestDivisor(int n) {
if (n % 2 == 0) {
return n / 2;
}
final int sqrtn = (int) Math.sqrt(n);
for (int i = 3; i <= sqrtn; i += 2) {
if (n % i == 0) {
return n / i;
}
}
return 1;
}
I don't know if you can do this in constant time, but you can certainly do it in less time than this.
Start with 2, and loop through all numbers, checking if n is divisible by that number. When you get to a number that divides n, then you can stop - your answer is n/i. If you get to the end and it still doesn't divide, then n is prime and the answer is just 1.
Instead of ending at n/2 if you don't find a divisor, you can end at √n with this method, which will reduce the big O.
Also, you could start with checking if it's divisible by 2, then go to 3 and only check the odd numbers from there. (If it was divisible by an even number, then it was divisible by 2.) That won't change the big O, but it should cut the processing time almost in half since you're only checking about half the divisors.
You know that if a is dividable by b, it is also dividable by a/b and the smaller b is, the larger is a/b, so once you have found the divisor, return n/divisor:
public static int largestDivisor(int n){
for(int i = 2; i <= n/2; i++)
if(n % i == 0) {
return n/divisor;
}
}
return 0; //or whatever you decide to return if there is no such divisor
}
This is also faster because:
divisors tend to become more rare the larger they get; and
you can already give up at sqrt(n).
So the most efficient approach would be:
public static int largestDivisor(int n){
int sqrtn = (int) Math.sqrt(n);
for(int i = 2; i <= sqrtn; i++)
if(n % i == 0) {
return n/divisor;
}
}
return 0;
}

Java program that converts binary numbers to decimal numbers. The input is a string of zeros and ones

I have to create a java program that converts binary to decimal using the following steps. Being new at this I did something, but I don't know what I did wrong or how to continue.
public class BinaryToDecimal {
public static void main(String args[]){
long sum = 0;
int result;
String s = "1001010101011010111001011101010101010101";
for(int i = s.length()-1; i <= 0; i--){
result = (int)Math.pow(2, i);
if(s.charAt(i) == '1')
sum=sum + result;
}
System.out.println(sum);
}
}
Use a loop to read (charAt()) each digit (0/1 char) in the input string, scanning from right to left;
Use the loop to build the required powers of 2;
Use a conditional statement to deal with 0 and 1 separately;
Debug using simple input, e.g. 1, 10, 101, and print intermediate values in the loop.
Use your program to find the decimal value of the following binary number:
1001010101011010111001011101010101010101
Do this only if your decimal value is at most 2147483647 or the maximum value an int can be in Java. If you don't know, just check the length of your string. If it's less than or equal to 32 i.e. 4 bytes, then you can use parseInt.:
int decimalValue = Integer.parseInt(s, 2);
Refer HERE for more info on the Integer.parseInt();
But if it's more, you can use your code. I modified your loop which is where your problem was:
String s = "1001010101011010111001011101010101010101";
long result = 0;
for(int i = 0; i < s.length(); i++){
result = (long) (result + (s.charAt(i)-'0' )* Math.pow(2, s.length()-i-1));
}
System.out.println(result);
The first thing I notice is that your binary number has more than 32 bits. This cannot be represented in the space of an int, and will result in overflow.
As a simpler answer, I ran the following and got the correct value at the end, it just uses simple bit shifts.
For each index in the string, if the character is 1, it sets the corresponding bit in the result.
public class BinaryToDecimal {
public static void main(String[] args) {
long sum;
String bin = "1001010101011010111001011101010101010101";
sum = 0;
for (int i = 0; i < bin.length(); i++) {
char a = bin.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
}
sum >>= 1;
System.out.println(sum);
}
}
The loop runs from i = s.length()-1 until i <= 0. This should be i>=0.
The next problem is "int result". It works fine with result as a long ;) (Reason: You calculate a 40-bit value at the MostSignificantBit, but Integers only use 32-bit)
Also: You start at the rightmost Bit with i=s.length()-1. But the power that you calculate for it is 2^(s.length()-1) though it should be 2^0=1.
The solution is: result = (long)Math.pow(2, s.length()-1-i)
Edit:
I really like the solution of user2316981 because of its clear structure (without Math.pow, should be faster by using shift instead). And loops from 0 to MSB as I do with Double&Add algorithm. Can't comment on it yet, but thanks for the reminder ;)
import java.util.*;
import java.lang.Math;
class deci {
int convert(int n) {
int tem=1,power=0;
int decimal=0;
for (int j=0;j<n;j++) {
if(n==0) {
break;
} else {
while(n>0) {
tem=n%10;
decimal+=(tem*(Math.pow(2,power)));
n=n/10;
power++;
}
}
}
return decimal;
}
public static void main(String args[]) {
System.out.print("enter the binary no");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
deci dc=new deci();
int i=dc.convert(n);
System.out.print(i);
}
}

Categories

Resources