Hey guys so in my interview question I was given something like this below. By the way this is my code to solve fib. I want to improve this my code to eliminate repetition of fibonacci sequence that might end up being repeated at the process. For example if fib(1) and fib(1) are repeated twice, how to do I avoid this from happening so the program can advance to unique sequence being processed.
I really want to know how to improve this code. My solution is below but when I debug it, I feel like I get lost understanding what is really happening.
Thanks.
public class Fib {
public static void main(String[] args) {
System.out.print(fibonacci(14));
}
private static int fibonacci(int n) {
int fibArray[] = new int[n];
if (n <= 0) {
return 1;
} else if (n == 1) {
return 1;
} else {
fibArray[0] = fibonacci(n - 1);
fibArray[1] = fibonacci(n - 2);
if (fibArray[0] == fibonacci(n - 1)) {
return fibonacci(n - 1) + fibonacci(n - 2);
} else if (fibArray[1] != fibonacci(n - 2)) {
return fibonacci(n - 1) + fibonacci(n - 2);
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
}
To solve the nth Fibonacci number, basic recursion like your answer is not the best way.
There is a complicated matrix method to solve Fibonacci that uses O(log(n)) runtime and O(log(n)) memory.
If you want performance and simplicity in your Fibonacci solution, this is a neat formula (though this is memorization and defeats the problem solving part of the interview):
Here is a Java method implementation:
public Long fibonacci(int n)
{
double sqrt5 = Math.sqrt(5);
int tmp1 = (int)(1+sqrt5)/2;
int tmp2 = (int)(1-sqrt5)/2;
return (long) Math.ceil((Math.pow(tmp1, n) - Math.pow(tmp2, n))/sqrt5);
}
This method looks O(1) but it's not quite as the Math.pow() is O(log(n)). It uses O(1) memory.
As #PavelS mentioned. Should be something similar to this where n is your parameter:
int a = 0;
int b = 1;
// In N steps compute Fibonacci sequence iteratively.
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
return a;
You need to store the value once computed. If value is present, dont compute again, just use it, else calculate and store:
public class Fib {
static int fibo[]=new int[100];
public static void main(String[] args) {
Arrays.fill(fibo, 0);
System.out.print(fibonacci(24));
}
private static int fibonacci(int n) {
if (n <= 0)
fibo[n]=0;
else if (n == 1)
fibo[n]= 1;
else if(fibo[n]==0)
fibo[n]=fibonacci(n-1)+fibonacci(n-2);
return fibo[n];
}
}
Lets generalize this a little.
There are many techniques that can be used to optimize a recursive function. Here are some of them:
Memoization: you may be able to reduce the cost of repeated calls to an (expensive) function f(n) with the same argument. This can be done by creating a map n -> f(n) and doing a map lookup before making the expensive call.
Converting recursion into iteration. A compiler for a functional programming language will typically do this automatically for simple cases (tail calls). The Java compiler won't (for technical reasons which are off track) ... but you can do the same optimization at the source code level.
Converting call-stack recursion into iteration with a stack-like data structure. This is something you might do in Java to avoid StackOverflowError exceptions in deeply recursive problems that are no amenable to other optimizations.
The solution might be to solve a recurrence relation rather than trying to compute it.
Obviously, not all techniques will work for any given problem.
The other answers give examples of most of approaches.
Approach #1 - #Dip
Approach #2 - #FirstStep
Approach #4 - #PhotometricStereo
Related
I have a task to write quicksort (on only posivite numbers) algorythm in Java (I can't use any imports but Scanner) but without recursion and without stack.
I have two question about it :
I do understeand iterative quicksort with stack and recursive version but i cannot imagine how to do it without it.
I have heard about some 'in place' implementation but i dont really get it - is it solution for my problem?
I would appreciate if anyone could show me a way to do it ( dont post implementation if you can, I just want to understeand it not copy someone's code) or recommend some book where I can find it ( or some similar problem ).
Is implementing sort by insertion for some small arrays a good idea? If so how big should be N in this code :
if (arraySize < N)
insertionSort
else
quickSort
fi
Apparently my task was to find only posivite numbers, here is my solution:
public static void quickSort(final int size) {
int l = 0;
int r = size - 1;
int q, i = 0;
int tmpr = r;
while (true) {
i--;
while (l < tmpr) {
q = partition(l, tmpr);
arr[tmpr] = -arr[tmpr];
tmpr = q - 1;
++i;
}
if (i < 0)
break;
l++;
tmpr = findNextR(l, size);
arr[tmpr] = -arr[tmpr];
}
}
private static int findNextR(final int l, final int size) {
for (int i = l; i < size; ++i) {
if (arr[i] < 0)
return i;
}
return size - 1;
}
private static int partition(int l, int r) {
long pivot = arr[(l + r) / 2];
while (l <= r) {
while (arr[r] > pivot)
r--;
while (arr[l] < pivot)
l++;
if (l <= r) {
long tmp = arr[r];
arr[r] = arr[l];
arr[l] = tmp;
l++;
r--;
}
}
return l;
}
My array to sort is an static array in my class.
It is based on finding and creating negative numbers.
Partition is created by using middle element in array but using median is also good (it depends on array).
I hope someone will find this usefull.
Just as a reference the Java8 implementation of Arrays.sort(int[]) uses a threshold of 47, anything less than that is sorted using insertion. Their quick sort implementation is however very complex with some initial overhead, so look upon 47 as an upper limit.
A Google of "non-recursive quicksort" produced a slew of answers ... including this one: Non recursive QuickSort "Your language may vary," but the basic principle won't.
I personally think that, if you're going to sort something, you might as well use Quicksort in all cases . . .
Unless, of course, you can simply use a sort() function in your favorite target-language and leave it to the language implementors to have chosen a clever algorithm (uhhhh, it's probably Quicksort...) for you. If you don't have to specify an algorithm to do such a common task, "don't!" :-)
I have to write a java code for the 'sieve of eratosthenes' algorithm to print out primes up to a given max value on the console but I'm not allowed to use arrays. Our professor told us it is possible to do only with the help of loops.
So I thought a lot and googled a lot about this topic and couldn't find an answer. I dont think it's possible at all because you have store the information which digits are already crossed out somewhere.
my code until now:
public static void main(String[] args) {
int n = 100;
int mark = 2;
System.out.print("Primes from 1 to "+n+": 2, ");
for (int i = 2; i <= n; i++) {
if(i % mark != 0){
System.out.print(i+", ");
mark = i;
}
}
}
-> So, i'm not allowed to do the "i % mark != 0" command with numbers which are multiples of the numbers i already printed but how am i supposed to make that clear without an array where i can delete numbers on indexes?
BUT if there is a solution I would be glad if someone could share it with me! :)
The solution can be in other programming languages, i can translate it to java myself if its possible.
Thank you in advance and best regards
Update: Thank you very much all of you, i really appreciate your help but I don't think it can be done with the basic structures. All the algorithms i have seen yet which print out primes by using basic structures are no sieve of eratosthenes. :(
The Sieve is about remembering the primes you found already. As far as I know there is no way to do this without arrays or lists and only with loops.
I checked some of the examples at RosettaCode at random and did not find one without an array and only loops.
If you add Classes and Methods as options you can come up with a recursive design:
public class Sieve
{
private int current;
private int max;
private Sieve parent;
public Sieve(int current, int max, Sieve parent )
{
this.current = current;
this.max = max;
this.parent = parent;
}
public static void main(String[] args)
{
int n = 100;
System.out.print("Primes from 1 to " + n + ":\n");
printPrimes(n);
}
private static void printPrimes(int i)
{
new Sieve(2,i,null).start();
}
private void start()
{
if(current <2 || max <2)
{
return;
}
if(this.current > max)
{
parent.print();
return;
}
for(int i = this.current+1;current<=max+1;i++)
{
if(this.testPrime(i))
{
new Sieve(i,this.max,this).start();
return;
}
}
}
private boolean testPrime(int i)
{
if(i%this.current != 0)
{
if(this.parent == null)
{
return true;
}
else
{
return this.parent.testPrime(i);
}
}
return false;
}
private void print()
{
if(this.parent != null)
{
this.parent.print();
}
System.out.print(" "+this.current);
}
}
This removes the array but uses Objects to store the Prime (each Sieve holds one prime)
I'm taking back what I said earlier. Here it is, the "sieve" without arrays, in Haskell:
sieve limit = [n | n <- [2..limit], null [i | i <- [2..n-1], j <- [0,i..n], j==n]]
It is a forgetful sieve, and it is very very inefficient. Uses only additions, and integer comparisons. The list comprehensions in it can be re-coded as loops, in an imperative language. Or to put it differently, it moves counts like a sieve would, but without marking anything, and thus uses no arrays.
Of course whether you'd consider it a "true" sieve or not depends on what is your definition of a sieve. This one constantly recreates and abandons them. Or you could say it reimplements the rem function. Which is the same thing to say, actually, and goes to the essence of why the sieve suddenly becomes so efficient when reuse - via arrays usually - becomes possible.
Today, my teacher asked us to implement the next expression using recursion in Java (where n is a value asked to the user):
It is possible? I can't find a proper solution for this problem, but I think I will need two recursive methods.
UPDATE
So far I have done this:
public static double sumatorio(int n){
if(n==1)
return 1;
else{
return (1 + ((n-1) * segundoSumatorio(n))) + sumatorio(n-1);
}
}
public static double segundoSumatorio(int n){
if(n==1)
return 1;
else
return 1/(double)n + segundoSumatorio(n-1);
}
It looks like it's correct, but when n=3 or greater, the result is not exact. Someone knows why?
Maybe there is an error related with losing precision.
I really appreciate any help you can provide.
Hints:
Yes. One possible solution does involve two recursive methods.
(And it is a good solution ... )
Factor the problem (and the solution) into two parts; e.g. the complete "sigma" and the embedded "sigma".
Here is your code fixed. Note how the 2nd sumatorio needs 2 parameters,
and how I don't change the second parameter while calling it recursively.
This is what your formula says and not what you implemented.
This is not a precision error, you could have figured that out
because this error sounds too big for a precision error for such
small values of n.
public class Test {
public static void main(String a[]) throws Exception {
System.out.println(sumatorio(1));
System.out.println(sumatorio(2));
System.out.println(sumatorio(3));
System.out.println(sumatorio(4));
}
public static double sumatorio(int n){
return sumatorio(n ,n);
}
public static double sumatorio(int n, int m){
if(n==1)
return 1;
else{
return (1 + ((n-1) * segundoSumatorio(m))) + sumatorio(n-1, m);
}
}
public static double segundoSumatorio(int n){
if(n==1)
return 1;
else
return 1/(double)n + segundoSumatorio(n-1);
}
}
If this task is too hard for you, try splitting it in smaller chunks. The question asks for a summation, implemented by recurse. I am confident you can do summation by implementing a loop. Something like:
int sum = 0;
for(int i = 1; i < n; i++){
sum = sum+i;
}
This will sum all numbers from 1 to (n-1).
You can convert the loop into recursion by writing a simple adding method:
int sum = 0;
int doSum(int n){
if(n <= 1){
return 1;
}
else{
return n + doSum(n - 1);
}
}
sum = doSum(n);
From here on I think you should be able to catch up.
Splitting the problem into smaller subproblems is a technique used by ALL programmers. Start small and easy, adding complexity as you go.
I need to load around 2MB of data quickly on startup of my Android application.
I really need all this data in memory, so something like SQLite etc. is not an alternative.
The data consists of about 3000 int[][] arrays. The array dimension is around [7][7] on average.
I first implemented some prototype on my desktop, and ported it to android. On the desktop, I simply used Java's (de)serialization. Deserialization of that data takes about 90ms on my desktop computer.
However on Android 2.2.1 the same process takes about 15seconds(!) on my HTC Magic. It's so slow that if I don't to the deserialization in a seperate thred, my app will be killed. All in all, this is unacceptably slow.
What am I doing wrong? Should I
switch to something like protocol buffers? Would that really speed up the process of deserialization of several magnitudes - after all, it's not complex objects that I am deserializing, just int[][] arrays?!
design my own custom binary file format? I've never done that before, and no clue where to start
do something else?
Why not bypass the built-in deserialization, and use direct binary I/O?
When speed is your primary concern, not necessarily ease of programming, you can't beat it.
For output the pseudo-code would look like this:
write number of arrays
for each array
write n,m array sizes
for each element of array
write array element
For input, the pseudo-code would be:
read number of arrays
for each array
read n,m array sizes
allocate the array
for each element of array
read array element
When you read/write numbers in binary, you bypass all the conversion between binary and characters.
The speed should be limited only by the data transfer rate of the file storage media.
after trying out several things, as Mike Dunlavey suggested, direct binary I/O seemed fastest. I almost verbatim used his sketched out version. For completeness however, and if someone else wants to try, I'll post my full code here; even though it's very basic and without any kind of sanity check. This is for reading such a binary stream; writing is absolutely analogous.
import java.io.*;
public static int[][][] readBinaryInt(String filename) throws IOException {
DataInputStream in = new DataInputStream(
new BufferedInputStream(new FileInputStream(filename)));
int dimOfData = in.readInt();
int[][][] patternijk = new int[dimofData][][];
for(int i=0;i<dimofData;i++) {
int dimStrokes = in.readInt();
int[][] patternjk = new int[dimStrokes][];
for(int j=0;j<dimStrokes;j++) {
int dimPoints = in.readInt();
int[] patternk = new int[dimPoints];
for(int k=0;k<dimPoints;k++) {
patternk[k] = in.readInt();
}
patternjk[j] = patternk;
}
patternijk[i] = patternjk;
}
in.close();
return patternijk;
}
I had the same kind of issues on a project some months ago. I think you should split your file in various parts, and only load relevant parts following a choice from the user for example.
Hope it will be helpful!
I dont know your data but if you optimize your loop, it will effect the deserialize time unbelievably.
if you look at example below
computeRecursively(30);
computeRecursivelyWithLoop(30); // 270 milisecond
computeIteratively(30); // 1 milisecond
computeRecursivelyFasterUsingBigInteger(30); // about twice s fast as before version
computeRecursivelyFasterUsingBigIntegerAllocations(50000); // only 1.3 Second !!!
public class Fibo {
public static void main(String[] args) {
// try the methods
}
public static long computeRecursively(int n) {
if (n > 1) {
System.out.println(computeRecursively(n - 2)
+ computeRecursively(n - 1));
return computeRecursively(n - 2) + computeRecursively(n - 1);
}
return n;
}
public static long computeRecursivelyWithLoop(int n) {
if (n > 1) {
long result = 1;
do {
result += computeRecursivelyWithLoop(n - 2);
n--;
} while (n > 1);
System.out.println(result);
return result;
}
return n;
}
public static long computeIteratively(int n) {
if (n > 1) {
long a = 0, b = 1;
do {
long tmp = b;
b += a;
a = tmp;
System.out.println(a);
} while (--n > 1);
System.out.println(b);
return b;
}
return n;
}
public static BigInteger computeRecursivelyFasterUsingBigInteger(int n) {
if (n > 1) {
int m = (n / 2) + (n & 1); // not obvious at first – wouldn’t it be
// great to have a better comment here?
BigInteger fM = computeRecursivelyFasterUsingBigInteger(m);
BigInteger fM_1 = computeRecursivelyFasterUsingBigInteger(m - 1);
if ((n & 1) == 1) {
// F(m)^2 + F(m-1)^2
System.out.println(fM.pow(2).add(fM_1.pow(2)));
return fM.pow(2).add(fM_1.pow(2)); // three BigInteger objects
// created
} else {
// (2*F(m-1) + F(m)) * F(m)
System.out.println( fM_1.shiftLeft(1).add(fM).multiply(fM));
return fM_1.shiftLeft(1).add(fM).multiply(fM); // three
// BigInteger
// objects
// created
}
}
return (n == 0) ? BigInteger.ZERO : BigInteger.ONE; // no BigInteger
// object created
}
public static long computeRecursivelyFasterUsingBigIntegerAllocations(int n) {
long allocations = 0;
if (n > 1) {
int m = (n / 2) + (n & 1);
allocations += computeRecursivelyFasterUsingBigIntegerAllocations(m);
allocations += computeRecursivelyFasterUsingBigIntegerAllocations(m - 1);
// 3 more BigInteger objects allocated
allocations += 3;
System.out.println(allocations);
}
return allocations; // approximate number of BigInteger objects
// allocated when
// computeRecursivelyFasterUsingBigInteger(n) is
// called
}
}
I am running a very simple program which simulate tower of hanoi.
I print the time taken to move n number (20 to 30) disks.
I see a strange pattern . It takes roughly the same amount of time to move n(even number) and n+1 disks. And to move n+2 disk it takes 4 times of n disks .
I have put the program below. I guess there is some optimization being done in vm when we have multiple recursion calls.
Can anyone put more light on this?
public class Hanoi {
public static void move(int n) {
if(n > 0) {
move(n-1);
move(n-1);
}
}
public static void main(String[] args) {
int N = 28;
move(12);
for(int n=18; n <= N; n++) {
long start = System.currentTimeMillis();
move(n);
long end = System.currentTimeMillis();
System.out.printf("n=%d t=%d i=%d\n",n, (end-start) , 10);
}
}
}
This "problem"? :-)
If you add IO or some decent computations to the move method, you will see that this behavior disappears. Also, if you just do one move recursive call, the program finishes immediately. Both of these timing anomalies are due to compiler and JIT optimization as Gunner mentioned. This version of your move method for example has much more expected timing:
static int[] pieces = new int[100];
public static void move(int n) {
if (n > 0) {
// random memory operations
pieces[n - 1] = pieces[n];
pieces[n] = pieces[n + 1];
pieces[n + 1] = pieces[n + 2];
move(n - 1);
move(n - 1);
}
}
Here's an interesting piece by IBM about tail recursion. Here's another blog posting about the topic.