I made a function that given a number n
, takes its digits and looks for the next number greater than it that can be formed with them.
Examples:
n = 513 => debe devolver 531
n = 9219 => debe devolver 9291
n = 123 => debe devolver 132
If the number cannot be formed, the function must return -1
. The problem is that this simple function is brute force and does not pass the speed test, because what it does is increase the number by 1
until it finds a number that has the same digits and in the case of a very large number it must do many comparisons in which:
- transform the number
- runs it
- orders it
- etc...
How can you improve the part where you compare if the digits of the number are the same as the number n
?
function nextBigger(n) {
const digitos = `${n}`.split('').sort((a, b) => a - b).join('');
if (n == mayorPosible) return -1
else {
do {
n++
} while (digitosNumero(n) != digitos)
}
return n
}
function mayorPosible(n) {
return Number(`${n}`.split('').sort((a, b) => b - a).join(''))
}
function digitosNumero(n) {
return `${n}`.split('').sort((a, b) => a - b).join('')
}
console.log(nextBigger(513));
console.log(nextBigger(2063));
console.log(nextBigger(1497));
The function should be something like this, the mechanics is not my invention, but geeksforgeeks 's , the implementation is mine, and there are many things that can be improved:
I added
infinity
always as the first element because I couldn't find a better way to solve the issue of checking if the first element needs to be moved. ThelastIndexOf
does not seem to be the best way to search the index.The steps should be:
What I think you can do is get the largest number that can be formed with the numbers by decomposing and ordering the digits of the number. If
n
it is equal to the number then a larger number can no longer be formed, and you return-1
:If the number is not yet the largest, then you decompose it into another vector (you can't use the first one because it's already ordered) and rotate its digits starting from the end, first you change the last one with the penultimate one, if it's not bigger you go back to change the penultimate with the penultimate and so on until you get a larger number:
And the code at the end would look like this:
As far as testing goes, it works fine.
Finding the largest possible number with certain digits is as simple as ordering the numbers from largest to smallest:
But what we want is to make the change to find the minimum greater number , with which we will have to see what numbers must be exchanged, from the units with the tens onwards:
Given an n-digit number, the digit in position n-1 is the units.
If the number in the tens (n-2) is smaller, exchanging it works for us.
If not, we proceed to compare with hundreds... but now we have to reorder the numbers that are on the right from least to greatest
If not, we proceed to compare with thousands... and the same thing happens to us, we have to reorder the remaining numbers:
Therefore, we already see a pattern: try to put a larger digit in a column than the unit, leaving the numbers to the left untouched and to the right ordered from smallest to largest:
As you can see, the execution is immediate even for very large numbers because it works with character arrays, ordering them, so the complexity is n(Log n) where n is the number of digits
I had deleted my previous answer because I wasn't near a computer to fix it and the results were wrong. Here I leave you a new solution, which now analyzing @PabloLozano's code does practically the same thing and looking at his implementation, it is most likely that his is more efficient than the one I am giving you.
Either way, I think either solution could pass your test, because they have much lower complexity than placing nested loops.