Problem statement :
On a positive integer, you can perform any one of the following 3 steps.
UPDATE: Here is updated code which I have actually tested somewhat and I believe comes to the same answers for n from 1 to 100000. I'm leaving the original answer below for reference. The flaw was the "clever" use of MAX_INT. I forgot that there would be some cases where I skipped the -1 possibility but the number would also not be divisible by 2 or 3. This solves that by returning null to mean "this path is pointless to explore further".
public static int steps(int n) {
return steps(n, 0);
}
private static Integer steps(int n, int consecutiveMinusOnes) {
if (n <= 1) {
return 0;
}
Integer minSteps = null;
if (consecutiveMinusOnes < 2) {
Integer subOne = steps(n - 1, consecutiveMinusOnes + 1);
if (subOne != null) {
minSteps = 1 + subOne;
}
}
if (n % 2 == 0) {
Integer div2 = steps(n / 2, 0);
if (div2 != null) {
if (minSteps == null) {
minSteps = div2 + 1;
} else {
minSteps = Math.min(minSteps, 1 + div2);
}
}
}
if (n % 3 == 0) {
Integer div3 = steps(n / 3, 0);
if (div3 != null) {
if (minSteps == null) {
minSteps = div3 + 1;
} else {
minSteps = Math.min(minSteps, 1 + div3);
}
}
}
return minSteps;
}
I believe this may work, but I haven't proved it. This algorithm is based on the idea that the only reason to subtract by one is to get you closer to a number divisible by 2 or 3. For this reason, you never really need to apply the subtract-by-one step more than two times consecutively, because if k % 3 == 2, then k - 2 % 3 == 0 and you can divide by three. Subtracting by one more times will be a wast of effort (you'll have also passed by at least one even number, so the best divide by two step opportunity will come up). This means a top down, recursive approach, and you can mix in some memoization if you want to:
public static int steps(n) {
return steps(n, 0);
}
private static int steps(int n, int consecutiveMinusOnes) {
if (n <= 1) {
return 0;
}
int minSteps = Integer.MAX_VALUE;
if (consecutiveMinusOnes < 2) {
minSteps = 1 + steps(n - 1, consecutiveMinusOnes + 1);
}
if (n % 2 == 0) {
minSteps = Math.min(minSteps, 1 + steps(n / 2, 0));
}
if (n % 3 == 0) {
minSteps = Math.min(minSteps, 1 + steps(n / 3, 0));
}
return minSteps;
}
DISCLAIMER: As I said above, I haven't proved this method works. I also haven't tested this particular implementation. I also haven't done the memoization stuff just because I'm lazy. Anyway, I hope that even if this doesn't quite work it gives you some ideas on how to modify your approach.