I'm working on a practice program at InterviewStreet and I have a solution that runs with a time of 5.15xx seconds, while the maximum time allowed for a java solution is 5 seconds. Is there anything I can do with what I've got here to get it under 5 seconds? There's also a limit of 256 MB so as near as I can tell this is both the most time and memory efficient solution to the problem...
edit:
The possible values for N and K are N <= 10^9 and K <= N, which is why I chose to do everything using BigInteger. The maximum number of trials is 10000. So basically, you input the number of trials, then a pair of integer values for each number of trials, and the program computes the three versions of the binomial coefficient for the equation in the second loop. I figured it would be faster to read everything into the arrays, then process the arrays and put the results into a third array to be processed by the third loop because I figured it might be faster that way. I tried doing everything in the same loop and it ran slower.
I've tried three or four different algorithms for calculating the binomial coefficient (nCr - or n choose r, all are different ways of saying the same thing). Some of the algorithms involve a two dimensional array like c[n][k]. This is the only solution I've submitted that didn't come back with some sort of memory error. The answer needs to be output mod (10 ^ 6) + 3 because the answers of nCr * nCr get pretty huge. A sample run of the program is:
3
4 1
5 2
90 13
2
5
815483
Can't run it on a faster machine because it needs to pass on their machine to count, basically I submit the code and they run it against their test cases, and I have no idea what their test case is, just that the inputs are within the bounds given above.
And the program itself:
import java.math.BigInteger;
import java.util.Scanner;
public class Solution {
public BigInteger nCr(int n, int r) {
if (r > n ) {
return BigInteger.ZERO;
}
if (r > n / 2) {
r = n - r;
}
BigInteger result = BigInteger.ONE;
for (int i = 0; i < r; i++) {
result = result.multiply(BigInteger.valueOf(n - i));
result = result.divide(BigInteger.valueOf(i + 1));
}
return result;
}
public static void main(String[] args) {
Scanner input = new Scanner( System.in );
BigInteger m = BigInteger.valueOf(1000003);
Solution p = new Solution();
short T = input.nextShort(); // Number of trials
BigInteger intermediate = BigInteger.ONE;
int[] r = new int[T];
int[] N = new int[T];
int[] K = new int[T];
short x = 0;
while (x < T) {
N[x] = input.nextInt();
K[x] = input.nextInt();
x++;
}
x = 0;
while (x < T) {
if (N[x] >= 3) {
r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
} else {
r[x] = 0;
}
x++;
}
x = 0;
while (x < T) {
System.out.println(r[x]);
x++;
}
}
}
Not entirely sure what the algorithm is trying to accomplish but I'm guessing something with binomial coefficients based on your tagging of the post.
You'll need to check if my suggestion modifies the result but it looks like you could merge two of your while loops:
Original:
while (x < T) {
N[x] = input.nextInt();
K[x] = input.nextInt();
x++;
}
x = 0;
while (x < T) {
if (N[x] >= 3) {
r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
} else {
r[x] = 0;
}
x++;
}
New:
x = 0;
while (x < T) {
//this has been moved from your first while loop
N[x] = input.nextInt();
K[x] = input.nextInt();
if (N[x] >= 3) {
r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
} else {
r[x] = 0;
}
x++;
}
try to run using a profilerm for example the jvisualvm and run this class with
-Dcom.sun.management.jmxremote
attach to the process and start a profile.
Related
I am doing an assignment where I must use nested loops in order to add up the squares and cubes of integers from 1 to N (N being whatever the user inputs). For example, if the user input the number 5, the program is supposed to do "1²+2²+3²+4²+5²" and output the sum of those numbers, as well "1³+2³+3³+4³+5³" and output the sum of those numbers.
However, I am having trouble figuring out how to code it in a way that I receive the proper output? This is what I wrote. Scanners were already added.
int limitNum = input.nextInt();
double squareNums:
double sumofSq = 0;
double cubedNums;
double sumofCubes = 0;
for(int s = 1; s <= limitNum; s++)
{
for(int c = 1; c <= limitNum; c++)
{
cubedNums = Math.pow(c, 3);
sumofCubes = sumofCubes + cubedNums;
}
squareNums= Math.pow(s, 2);
sumofSq = sumofSq + squareNums;
}
But currently, when I run this program, the sum of the squares output correctly, but the sum of the cubes is always some big number. For example if 5 is used, sumofSq would output 55.0, but sumofCubes would output 1125.0.
There is no point using a nested loop as this would result in complexity of O(n²). A single loop would be sufficient and be in complexity class O(n).
public class Application {
public static void main(String[] args) {
var squareSum = 0d;
var cubeSum = 0d;
var upperBound = 5;
for(var i = 1; i <= upperBound; i++){
squareSum += Math.pow(i, 2);
cubeSum += Math.pow(i, 3);
}
System.out.printf("""
Sum of first n squares: %s
Sum of first n cubes: %s
""", (int)squareSum, (int)cubeSum);
}
}
In fact there is no need to loop at all => constant computation time no matter the size of the input O(1). There is a well known formula which tells you the sum of the first n squares.
n(n+1)(2n+1)
------------
6
Please see this for a proof.
The same holds true for the first n cubes.
n²(n+1)²
--------
4
Please see this for a proof.
The following program will therefore return the same result.
public class Application {
public static void main(String[] args) {
var upperBound = 5;
System.out.printf("""
Sum of first n squares: %s
Sum of first n cubes: %s
""", sumOfFirstNSquares(upperBound), sumOfFirstNCubes(upperBound));
}
public static int sumOfFirstNSquares(int n){
return (n * (n+1) * (2 * n + 1)) / 6;
}
public static int sumOfFirstNCubes(int n){
return ((n * n) * (n+1) * (n+1)) / 4;
}
}
In fact there is no need to loop at all => constant computation time no matter the size of the input O(1). There is a well known formula which tells you the sum of the first n squares.
java
This question already has answers here:
nᵗʰ ugly number
(13 answers)
Closed 2 years ago.
I am trying to solve the LeetCode ugly number challenge II. I came up with an algorithm of my own, seems working in theory but does not. I want to know why. I implemented this in Java but I write in Python normally, so if you correct the Java code, would appreciate.
The problem statement is:
"Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2,
3, 5.
Example:
Input: n = 10 Output: 12 Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10 ugly numbers. Note:
1 is typically treated as an ugly number. n does not exceed 1690."
This is my code:
class Solution {
public int nthUglyNumber(int n) {
// Gather all the uglies in one place
int[] uglies = new int[n];
// Set first one as one
uglies[0] = 1;
// Start filling
for (int i = 1; i < uglies.length - 1; i++) {
int num = i;
if (isUgly(num) == true) {
uglies[i] = num;
} else {
while (isUgly(num) == false) {
num++;
}
uglies[i] = num;
System.out.println(uglies[i]);
}
}
return uglies[uglies.length - 1];
}
public boolean isUgly(int m) {
boolean ans = false;
// Check if the number is divisible by an integer other than 2,3 or 5
// Simply iterate through numbers smaller than n to find a smaller divisor
for (int i = 2; i < m; i++) {
// If n is divisable by i and i is not a multiple of 2,3 or 5
boolean other_divisor = (m % i == 0) && (i % 2 != 0 || i % 3 != 0 || i % 5 != 0);
if (other_divisor == true) {
ans = false;
} else {
ans = true;
}
}
return ans;
}
}
So I basically made a function isUgly(n), which takes a number and checks if it is ugly by finding out if it has a divisor other than 2,3,5. If there is, then it should not be an ugly number. Than in the main body I go over all integers and check if they are ugly. If they are, I add them to an array until I fill out the n-th position. Would appreciate if corrected.
Not sure where your bug is. But, it has to be solved efficiently (time and space).
These solutions would pass through LeetCode, yet are not the most efficient algorithms for the problem. Since the question is math related, pretty sure there are many ways to make it much efficient.
C++
#include <vector>
class Solution {
public:
int nthUglyNumber(int n) {
int factor_two = 0;
int factor_three = 0;
int factor_five = 0;
std::vector<int> uglies(n);
uglies[0] = 1;
for (int index = 1; index < n; index++) {
uglies[index] = std::min(uglies[factor_five] * 5, std::min(uglies[factor_two] * 2, uglies[factor_three] * 3));
if (uglies[index] == uglies[factor_two] * 2) {
factor_two++;
}
if (uglies[index] == uglies[factor_three] * 3) {
factor_three++;
}
if (uglies[index] == uglies[factor_five] * 5) {
factor_five++;
}
}
return uglies[n - 1];
}
};
Java
public class Solution {
public int nthUglyNumber(int n) {
int[] uglies = new int[n];
uglies[0] = 1;
int indexTwo = 0;
int indexThree = 0;
int indexFive = 0;
int two = 2;
int three = 3;
int five = 5;
for (int index = 1; index < n; index++) {
int minFactor = Math.min(five, Math.min(two, three));
uglies[index] = minFactor;
if (minFactor == two) {
two = 2 * uglies[++indexTwo];
}
if (minFactor == three) {
three = 3 * uglies[++indexThree];
}
if (minFactor == five) {
five = 5 * uglies[++indexFive];
}
}
return uglies[n - 1];
}
}
Python
class Solution:
def nthUglyNumber(self, n: int) -> int:
uglies = (1,)
factor_two = factor_three = factor_five = 0
while len(uglies) < n:
while uglies[factor_two] * 2 <= uglies[-1]:
factor_two += 1
while uglies[factor_three] * 3 <= uglies[-1]:
factor_three += 1
while uglies[factor_five] * 5 <= uglies[-1]:
factor_five += 1
curr_ugly = min(uglies[factor_two] * 2, uglies[factor_three] * 3, uglies[factor_five] * 5)
uglies += (curr_ugly,)
return uglies[-1]
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
If you are preparing for interviews:
We would want to write bug-free and clean codes based on standards and conventions (e.g., c1, 2, c++1, 2, java1, 2, c#1, 2, python1, javascript1, go1, rust1). Overall, we would like to avoid anything that might become controversial for interviews.
There are also other similar platforms, which you might have to become familiar with, in case you'd be interviewing with specific companies that would use those platforms.
If you are practicing for contests1:
Just code as fast as you can, almost everything else is very trivial.
For easy questions, brute force algorithms usually get accepted. For interviews, brute force is less desired, especially if the question would be an easy level.
For medium and hard questions, about 90% of the time, brute force algorithms fail mostly with Time Limit Exceeded (TLE) and less with Memory Limit Exceeded (MLE) errors.
Contestants are ranked based on an algorithm explained here.
I'm doing a coding challenge online where I'm supposed to write a class that takes in a positive parameter ("num") and returns its multiplicative persistence. This is the number of times you must multiply the digits in "num" until you reach a single digit.
For example, the multiplicative persistence of 39 = 3. This is because:
3 * 9 = 27
2 * 7 = 14
1 * 4 = 4
This is the whole program so far:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class Persist {
public static void main(String[] args) {
persistence(39);
}
public static int persistence(long num) {
int persistenceValue = 0;
List<Long> digitList = new ArrayList<Long>();
long lastDigit;
//Resolves if num is single digit
if (num <= 9) {
return 0;
}
//Takes each digit of number and stores it to digitList (backwards)
while (num > 0) {
lastDigit = (num % 10);
digitList.add(lastDigit);
num = num / 10;
}
//Takes each digit in digitList and stores it in array in correct order
for (Long d : digitList) {
Long[] currentDigitArray = new Long[digitList.size()];
for (int i = 0; i < currentDigitArray.length; i++) {
currentDigitArray[currentDigitArray.length - i] = d;
}
persistenceValue = currentDigitArray.length;
while (persistenceValue > 1) {
List<Long> productList = multiplyDigits(currentDigitArray);
persistenceValue++;
}
}
return persistenceValue;
}
public static List multiplyDigits(Long[] currentDigitArray) {
//multiplies each digit
List<Long> productList = new ArrayList<Long>();
for (int i = 0; i < currentDigitArray.length; i++) {
Long product = currentDigitArray[i] * currentDigitArray[i + 1];
productList.add(product);
}
return productList;
}
}
I keep running into an array out of bounds exception for the for loop on line 52:
//Takes each digit in digitList and stores it in an array
for (Long d : digitList) {
Long[] currentDigitArray = new Long[digitList.size()];
for (int i = 0; i < currentDigitArray.length; i++) {
currentDigitArray[currentDigitArray.length - i] = d;
// ^ exception is thrown here ^
}
So obviously I looked this up on Google like a good stack overflow user. An array-index out of bounds exception is a Java exception thrown due to the fact that the program is trying to access an element at a position that is outside an array limit, hence the words "Out of bounds."
The problem is that I have no idea how big that array is going to be up front because it's all going to depend on how many digits are passed in by the user. I hard coded 39, but eventually I want the user to be able to put in as many as they want.
So how else would I takes each digit in digitList and store it in array?
This part has been resolved, but now I have a similar problem on line 78:
public static List multiplyDigits(Long[] currentDigitArray) {
//multiplies each digit
List<Long> productList = new ArrayList<Long>();
for (int i = 0; i < currentDigitArray.length; i++) {
Long product = currentDigitArray[i] * currentDigitArray[i + 1];
//^This line here
productList.add(product);
}
return productList;
}
I feel like this is a very similar problem, but don't quite know how to fix it.
This assignment
currentDigitArray[currentDigitArray.length - i] = d;
should be
currentDigitArray[currentDigitArray.length - 1 - i] = d;
to avoid the problem.
With this said, you can avoid arrays entirely by performing multiplication as you go. Recall that the order in which you do multiplication does not change the result. Therefore, you can start multiplication from the back of the number, and arrive at the same solution.
Arrays are zero-indexed, so currentDigitArray.length is always going to be out of bounds. In fact, because of the additive identity property, currentDigitArray.length - i is going to be currentDigitArray.length when i is 0. To fix this, just subtract an extra 1 in your index calculation:
currentDigitArray[currentDigitArray.length - i - 1] = d;
For your second problem, you iterate one element too many, and you need to stop one element earlier:
for (int i = 0; i < currentDigitArray.length - 1; i++) {
I've been trying to write a small and simple program that converts dec numbers to bin.The idea is that when the user enters a positive integer a for- cycle have to go through all the rounds of deviding the number /2 but it also have to get the tail (idk the math term really the actuall bin numbers) and write them in an array, thats the part Im having trouble with.I have predefined the array size of 30 (cant find a way to make a working array without specifying it's length) my idea was that then I could make a reversed array with length = index(i from the first for cycle) from the previous array with another for cycle etc. but when I tested the first array all I get is empty brackets printed: [] or nothing at all, eclipse doesnt find any errors in the code and I cant figure out whats wrong.I could use some help.Anyways here's the code:
public static void decToBin(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
int[] ostataci = new int[30];
for (int i = 0;n <= 0;i++){
ostataci[i] = n % 2;
n = n / 2;
// System.out.printf("%d %n", ostataci[i]); - even this one doesnt print at all
}
// System.out.println(Arrays.toString(ostataci)); - nor this one
}
}
Thanks for the replies Ive learnt a few new things.But since Im a newbie I wanted to do it with the metod I described thx for pointing me the error in the for cycle, that was my biggest problem, anyway heres the last code I wrote( working correctly) thats what I was trying to do from the beggining.
public static void decToBin2(){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
int i = 0;
int[] ostataci = new int[32];
if (n <= 0) {System.out.println("ERROR:n<=0");return;}
else if (n > 0){
while (n > 0){
i++;
ostataci[i] = n % 2;
n = n / 2;
}
}
int reverse = i;
int[] reversed = new int[reverse];
for (int i2 = 0;i2 != reverse;i--,i2++){
reversed[i2] = ostataci[i];
System.out.print(reversed[i2]);
}
}
The immediate error is in the for loop:
else if (n > 0) {
// Since n > 0 it'll never run
for (int i = 0;n <= 0;i++)
The implementation itself could be something like that (keep it simpler!):
...
if (n <= 0)
System.out.println("ERROR:n<=0");
else {
// Why do we need array/ArrayList etc.? We are supposed to build a string!
StringBuilder Sb = new StringBuilder();
// while we have something to do...
// (are we supposed to compute exact number of steps? No)
while (n > 0) {
Sb.insert(0, n % 2);
n /= 2;
}
System.out.println(Sb.toString());
}
Your loop for (int i = 0;n <= 0;i++){ } won't execute because you know that n is positive (by your if condition), but the for condition demands that n be negative (n <= 0). I suspect you mean n>0 instead.
As for variable length arrays you can use Lists, although that might be better to add in later
your for loop is wrong for (int i = 0;n <= 0;i++){ this just wont run change it to something like this while (n > 0) { and your code will works fine. also int is 32 bit so change int[] ostataci = new int[30]; to int[] ostataci = new int[32]; although it is better to uselist instead of array.
Decimals are already converted to binary on the computer, why don't you use bit wise operations to check the saved integer? Eg to check if bit n of an int is set, evaluate the boolean (number >> n) & 1. Just put that in a loop and you're done. Everyone else is making it too complicated.
Here is an alternative approach, using the shift operator and bit-masking:
public static int[] dec2bin(int n) {
int[] result = new int[32];
for (int i = 0; i < 32; i++) {
result[31-i] = n & 0x1;
n >>= 1;
}
return result;
}
This will also work just fine for negative numbers.
Example usage:
public static void main(String[] args) {
int[] result = dec2bin(5);
for (int i : result)
System.out.print(i);
System.out.flush();
}
Ouput:
00000000000000000000000000000101
Explaination
The code n & 0x1 from above is bit-masking. The 0x1 is hex notation for the number 1. In binary, that number looks like this:
00000001
In the first iteration of the for loop, n looks like:
00000101
The & operator does a bit-by-bit (bitwise) comparison of the bits in the two numbers, 'anding' them together, producing a new number based on those comparisons. If either or both of the corresponding bits are 0, the resulting bit is 0. If both of them are 1, the resulting bit is 1. So, for the two numbers listed above, the result of 'anding' them together is:
00000001
Or, in decimal, 1. You'll note that that also happens to be the bit value of the rightmost bit in n. Which we save into the result array at the rightmost index.
Next, we shift (>>) n right by 1. This moves every bit along by one (the rightmost bit is lost), and the resulting n is now:
00000010
We repeat that process 32 times (for each of the 32 bits of an int) and at the end we get a result array containing the correct answer.
Try this:
package mypackage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.Arrays;
public class Converter{
final static int ARRAY_SIZE = 30;
public static void main(String[] args){
int n;
Scanner in = new Scanner(System.in);
System.out.println("Enter a positive integer:");
n = in.nextInt();
in.close();
if (n <= 0){
System.out.println("ERROR:n<=0");
return;
}else if (n > 0){
int[] ostataci = new int[ARRAY_SIZE];
int i = 0;
while (n>0){
ostataci[i] = n % 2;
i++;
n = n / 2;
System.out.printf("%d %n", ostataci[i]);
}
System.out.println("All done!");
System.out.println(Arrays.toString(ostataci));
}
}
}
I'm working on Project Euler problem #2:
Each new term in the Fibonacci sequence is generated
by adding the previous two terms. By
starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
My code:
public class Two {
public static void main(String[] args) {
Two obj = new Two();
int sum = 0, i = 1;
while (obj.fibonacci(i) < 4000001) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
i++;
}
}
System.out.println(sum);
}
public int fibonacci(int n) {
if (n == 0) {
return -1;
}
if (n == 1) {
return 1;
}
if (n == 2) {
return 3;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
Please help me that what is wrong with this code that when I run it. It doesn't show the output on the console and the total time will be over than 5 minutes
Thanks
You're stuck in an infinite loop there as you're only increasing i when its mod 2 is equal to 0. You need to move your i++ lower.
while (obj.fibonacci(i) <= 4000000) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
}
i++;
}
As other comments have metioned, this isn't the best way to solve the fibonacci problem, but it solves your error/problem. You should walk this through a debugger if you don't see why and you'll notice you use a lot of recursive calls which have already been solved. Since you're calling it numerous times in the code, (in the while statement and in the if statement) you've increased your processing time.
Here is a sample of your fibonacci calls, notice how you call the fibonacci method on the same number multiple times:
1
2
3
2
1
4
3
2
1
2
5
As mentioned, the i++ needs to be moved outside the check for eveness or you'll be stuck in a loop.
But you have a slightly bigger problem. The fibonacci sequence starts with
...1, 2, 3, ...
where instead you have ...1, 3, ... which means you get incorrect results. You should have:
// ...
if (n == 2) {
return 2;
// ...
Although you solution might work, it is quite expensive as it recalculates results already obtained.
Using recursion in this case, to have the value of fibonacci(4), you recursively add the values of fibonacci(3) and fibonacci(2), which you already calculated previously.
Try with storing your values in a list instead of recomputing all the time:
List<Long> fibonacci = new ArrayList<Long>();
// First terms
fibonacci.add(-1L); // 0 is dummy, sequence starts at 1
fibonacci.add(1L);
fibonacci.add(2L);
for (int i = 3; fibonacci.get(i - 1) + fibonacci.get(i - 2) < 4000001; i++) {
long u = fibonacci.get(i - 1) + fibonacci.get(i - 2);
fibonacci.add(i, u);
}
Using this technique, you can compute the Fibonacci sequence up to 4000000 in less than 2 seconds (as I tried on my computer).
Then, just add some code to compute the sum inside the loop :-)
One of your problems is that you're excessively using recursion. You should try to store results to avoid to recalculate everything every time.
There's no reason to store the whole sequence of Fibonacci numbers in this case. You can simply "walk" along the sequence with a few local variables, summing as you go.
int fib2 = 0, fib1 = 1, fib0 = fib1 + fib2;
int sum = 0;
while (fib0 <= N)
{
if (fib0 % 2 == 0) sum += fib0;
fib2 = fib1;
fib1 = fib0;
fib0 = fib1 + fib2;
}
An improvement on #Blastfurnace's solution is to note that every third value is even.
public static void main(String[] args) {
long sum = 0;
int runs = 30000;
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long start = System.nanoTime();
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long time = System.nanoTime() - start;
System.out.println(sum+" took "+time/runs+" ns avg");
}
private static long sumEvenFib() {
int sum = 0;
for(int f1 = 1, f2 = 2;f2 < 4000001;) {
sum += f2;
int f3 = f1 + f2;
f1 = f3 + f2;
f2 = f1 + f3;
}
return sum;
}
On my old labtop this takes about 40 ns. or 0.000000040 seconds.
I think you can improve fibonacci next way:
def fib(x)
if(x==0 or x==1) then
return x;
end
a,b = 0,1
(x-1).times{ a,b = b,a+b; }
return b;
end
In other words convert recursion to iteration.
I think the question in already ambiguous.
The sum of all even valued should be below 4 million, or should the biggest even valued number be below 4 million?