try
with resources
Scanner in = new Scanner(System.in);
My IDE complains because this is never closed.
try (Scanner in = new Scanner(System.in)) {
Now it will close the Scanner
automatically when it leaves the try
block.
Not such a big deal with a Scanner
. May matter more with other resources that follow the same pattern.
Indent odd
for(int i = 0; i < T; i++){
int number = in.nextInt();
This is an eight column indent, but everywhere else you only have a four column indent per level. Why not make this match?
for (int i = 0; i < T; i++) {
int number = in.nextInt();
Note that since you never use i
or T
except here, you could also say
for (int T = in.nextInt(); T > 0; T--) {
int number = in.nextInt();
Then you don't have to maintain an extra variable. Of course, you may find the other version more readable.
Don't repeat common operations
if (number - powerNumber < minDiff)
minDiff = number - powerNumber;
Note that number
is constant for the entire for
loop and minDiff
only changes a small portion of the time. So calculate that after you finish.
int closestValue = 1;
Note that \$1^e = 1\$ is the smallest possible power.
And then use it
if (closestValue < powerNumber)
closestValue = powerNumber;
And finally change
System.out.println(minDiff);
to
System.out.println(number - closestValue);
This will produce the same result, but it moves a subtraction that you do on every iteration of the loop out of the loop. So you only do it once.
Don't use Math.pow
when you could just multiply
You say
for (int e = 1; (powerNumber = (int) Math.pow(b, e)) <= number; e++) {
Why not just say
for (int powerNumber = b; powerNumber <= number; powerNumber *= b) {
This replaces an expensive power operation with a cheaper multiplication.
Go the other direction
for (int b = 2; b <= sqrtNumber; b++) {
You start with the smallest possible base (2) and increase up to the square root. As a result, you have to update either minDiff
or closestValue
on every iteration of the inner loop.
for (int b = (int)Math.sqrt(number); b >= 2; b--) {
Now you start with the largest possible base. So you update at most twice for any value of b
.
A side benefit of this is that we can get rid of sqrtNumber
as unnecessary. It was only needed previously since we used it in the loop comparison.
for (int b = (int)Math.sqrt(number); b >= 2 && closestValue != number; b--) {
This short circuits if we find an exact match. Obviously we won't find a better match, so we can stop looking.
This should be benchmarked, since we don't know if it will stop early often enough to make up for the extra comparison.
Summary
public static void main(String[] args) {
try (Scanner in = new Scanner(System.in)) {
for (int T = in.nextInt(); T > 0; T--) {
int number = in.nextInt();
int closestValue = 1;
for (int b = (int)Math.sqrt(number); b >= 2 && closestValue != number; b--) {
for (int powerNumber = b; powerNumber <= number; powerNumber *= b) {
if (closestValue < powerNumber) {
closestValue = powerNumber;
}
}
}
System.out.println(number - closestValue);
}
}
}
I would expect this to be faster than your original code, although @Tunaki's version is probably still faster than this for larger inputs.
e
should never be1
. (I think?) Don't think that would likely be enough to shave 2 seconds off though. \$\endgroup\$