Acabo de bombardear una entrevista e hice casi cero progreso en mi pregunta de entrevista. ¿Alguien puede decirme cómo hacer esto? Intenté buscar en línea pero no pude encontrar nada:
Dado un número, encuentre el siguiente número más alto que tenga exactamente el mismo conjunto de dígitos que el número original. Por ejemplo: dado 38276 retorno 38627
Quería comenzar por encontrar el índice del primer dígito (desde la derecha) que fuera menor que el dígito de las unidades. Luego rotaría los últimos dígitos del subconjunto de modo que fuera el siguiente número más grande compuesto por los mismos dígitos, pero se atascó.
El entrevistador también sugirió intentar cambiar los dígitos de uno en uno, pero no pude descifrar el algoritmo y simplemente miré una pantalla durante unos 20-30 minutos. No hace falta decir que creo que voy a tener que continuar la búsqueda de empleo.
editar: por lo que vale, me invitaron a la próxima ronda de entrevistas
next_permutation
;-)Respuestas:
Puede hacerlo en
O(n)
(donden
está el número de dígitos) así:Comenzando por la derecha, encontrará el primer par de dígitos de modo que el dígito izquierdo sea más pequeño que el dígito derecho. Vamos a referirnos al dígito izquierdo por "dígito-x". Encuentre el número más pequeño más grande que digit-x a la derecha de digit-x, y colóquelo inmediatamente a la izquierda de digit-x. Finalmente, clasifique los dígitos restantes en orden ascendente, ya que ya estaban en orden descendente , todo lo que necesita hacer es invertirlos (guarde para el dígito-x, que se puede colocar en el lugar correcto
O(n)
) .Un ejemplo lo aclarará más:
Prueba de corrección:
Usemos letras mayúsculas para definir cadenas de dígitos y minúsculas para los dígitos. La sintaxis
AB
significa "la concatenación de cadenasA
yB
" .<
es el ordenamiento lexicográfico, que es lo mismo que el ordenamiento de enteros cuando las cadenas de dígitos son de igual longitud.Nuestro número original N es de la forma
AxB
, dondex
es un solo dígito yB
se ordena descendente.El número encontrado por nuestro algoritmo es
AyC
, dondey ∈ B
es el dígito más pequeño> x
(debe existir debido a la forma en quex
se eligió, ver arriba) , yC
se ordena de forma ascendente.Suponga que hay algún número (usando los mismos dígitos)
N'
tal queAxB < N' < AyC
.N'
debe comenzar conA
o de lo contrario no podría caer entre ellos, para que podamos escribirlo en el formularioAzD
. Ahora nuestra desigualdad esAxB < AzD < AyC
, que es equivalente axB < zD < yC
donde las cadenas de tres dígitos contienen los mismos dígitos.Para que eso sea cierto, debemos tenerlo
x <= z <= y
. Puesto quey
es el dígito más pequeño> x
,z
no puede ser de entre ellos, así que oz = x
oz = y
. Decirz = x
. Entonces nuestra desigualdad esxB < xD < yC
, lo que significaB < D
que tantoB
yD
tienen los mismos dígitos. Sin embargo, B se ordena descendente, por lo que no hay una cadena con esos dígitos más grandes que ella. Por lo tanto no podemos tenerB < D
. Siguiendo los mismos pasos, vemos que siz = y
, no podemos tenerD < C
.Por
N'
lo tanto , no puede existir, lo que significa que nuestro algoritmo encuentra correctamente el siguiente número más grande.fuente
9 832
luego ordenar todo a la derecha de 9:9238
Un problema casi idéntico apareció como un problema de Code Jam y tiene una solución aquí:
http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1
Aquí hay un resumen del método usando un ejemplo:
A. Divida la secuencia de dígitos en dos, de modo que la parte derecha sea lo más larga posible mientras permanezca en orden decreciente:
(Si el número completo está en orden decreciente, no se puede hacer un número mayor sin agregar dígitos).
B.1 Seleccione el último dígito de la primera secuencia:
B.2 Encuentre el dígito más pequeño en la segunda secuencia que sea más grande que él:
B.3 Intercambiarlos:
C. Ordenar la segunda secuencia en orden creciente:
D. ¡Listo!
fuente
Aquí hay una solución compacta (pero en parte fuerza bruta) en Python
En C ++, podría realizar las permutaciones de esta manera: https://stackoverflow.com/a/9243091/1149664 (es el mismo algoritmo que el de itertools)
Aquí hay una implementación de la respuesta superior descrita por Weeble y BlueRaja, (otras respuestas). Dudo que haya algo mejor.
fuente
type 'map' has no len()
. Simplemente cambiaría la segunda línea aiis=list(map(int,str(ii)))
. ¿Y alguien podría explicar laif i == 0: return ii
línea por favor? ¿Por qué funcionaría con entradas como 111 o 531? Gracias.i == len(iis)
.Como mínimo, aquí hay un par de soluciones basadas en String de fuerza bruta, que deberías haber sido capaz de encontrar desde la parte superior de tu cabeza:
la lista de dígitos
38276
ordenados es23678
la lista de dígitos
38627
ordenados es23678
Incremento de fuerza bruta, clasificación y comparación
A lo largo de la fuerza bruta, las soluciones se convertirían en una Cadena y fuerza bruta todos los números posibles usando esos dígitos.
Cree entradas a partir de todas ellas, colóquelas en una lista y ordénelas, obtenga la siguiente entrada después de la entrada de destino.
Si pasaste 30 minutos en esto y no lograste al menos un enfoque de fuerza bruta, tampoco te contrataría.
En el mundo de los negocios, una solución que es poco elegante, lenta y torpe pero que hace el trabajo siempre es más valiosa que ninguna solución, de hecho, que describe prácticamente todo el software de negocios, poco elegante, lento y torpe.
fuente
fuente
Tu idea
está bastante bien, en realidad. Solo tiene que considerar no solo el último dígito, sino todos los dígitos de menor importancia que el actualmente considerado. Desde antes de que se alcance eso, tenemos una secuencia monotónica de dígitos, que es el dígito más a la derecha más pequeño que su vecino derecho. Considerar
El siguiente número más grande que tiene los mismos dígitos es
El dígito encontrado se intercambia por el último dígito, el más pequeño de los dígitos considerados, y los dígitos restantes se ordenan en orden creciente.
fuente
Estoy bastante seguro de que su entrevistador estaba tratando de empujarlo suavemente hacia algo como esto:
No es necesariamente la solución más eficiente o elegante, pero resuelve el ejemplo proporcionado en dos ciclos y cambia los dígitos uno a la vez como sugirió.
fuente
Toma un número y divídelo en dígitos. Entonces, si tenemos un número de 5 dígitos, tenemos 5 dígitos: abcde
Ahora intercambie dye y compare con el número original, si es más grande, tiene su respuesta.
Si no es más grande, cambie e y c. Ahora compare y si es más pequeño intercambie dye nuevamente (observe la recursividad), tome el más pequeño.
Continúe hasta que encuentre un número mayor. Con la recursividad, debería funcionar como unas 9 líneas de esquema, o 20 de c #.
fuente
Esa es una pregunta muy interesante.
Aquí está mi versión de Java. Tómeme aproximadamente 3 horas desde que descubrí el patrón para terminar completamente el código antes de revisar los comentarios de otros colaboradores. Me alegra ver que mi idea es la misma con los demás.
O (n) solución. Honestamente, fracasaré en esta entrevista si el tiempo es de solo 15 minutos y requiero terminar el código completo en la pizarra.
Aquí hay algunos puntos interesantes para mi solución:
Puse comentarios detallados en mi código, y el Big O en cada paso.
Aquí está el resultado que se ejecuta en Intellj:
fuente
Una implementación de JavaScript del algoritmo de @ BlueRaja.
fuente
Una solución (en Java) podría ser la siguiente (estoy seguro de que los amigos aquí pueden encontrar una mejor):
Comience a intercambiar dígitos desde el final de la cadena hasta obtener un número más alto.
Es decir, primero comienza a subir el dígito inferior, luego el siguiente más alto, etc.
Luego ordena el resto. En su ejemplo obtendría:
fuente
63872
Por qué, qué debería ser?Si está programando en C ++, puede usar
next_permutation
:fuente
100
? :-)No sabía nada sobre el algoritmo de fuerza bruta cuando respondí esta pregunta, así que lo enfoqué desde otro ángulo. Decidí buscar en toda la gama de posibles soluciones en las que este número podría reorganizarse, comenzando desde number_given + 1 hasta el número máximo disponible (999 para un número de 3 dígitos, 9999 para 4 dígitos, etc.). Hice este tipo de búsqueda de un palíndromo con palabras, ordenando los números de cada solución y comparándolo con el número ordenado dado como parámetro. Entonces simplemente devolví la primera solución en la matriz de soluciones, ya que este sería el siguiente valor posible.
Aquí está mi código en Ruby:
fuente
Código PHP
fuente
Solo he probado esto con dos números. Ellos trabajaron. Como gerente de TI durante 8 años hasta que me jubilé en diciembre pasado, me preocupaban tres cosas: 1) Precisión: es bueno si funciona, siempre. 2) Velocidad: debe ser aceptable para el usuario. 3) Claridad: probablemente no soy tan inteligente como tú, pero te pago. Asegúrate de explicar lo que estás haciendo, en inglés.
Omar, mucha suerte en el futuro.
fuente
Para una buena descripción de cómo hacer esto, vea " Algoritmo L " en " El arte de la programación de computadoras: generar todas las permutaciones " de Knuth (.ps.gz).
fuente
Aquí está mi código, es una versión modificada de este ejemplo.
Biblioteca:
Prueba:
fuente
Agregue 9 al número de n dígitos dado. Luego verifique si está dentro del límite (el primer número de dígitos (n + 1)). Si es así, verifique si los dígitos del nuevo número son los mismos que los dígitos del número original. Repita agregando 9 hasta que ambas condiciones sean verdaderas. Detenga el algo cuando el número vaya más allá del límite.
No pude encontrar un caso de prueba contradictorio para este método.
fuente
Solo otra solución usando python:
Salida:
fuente
fuente
A continuación se muestra el código para generar todas las permutaciones de un número ... aunque primero hay que convertir ese entero en una cadena usando String.valueOf (entero).
fuente
fuente
Otra implementación de Java, ejecutable de fábrica y completada con pruebas. Esta solución es O (n) espacio y tiempo utilizando una buena programación dinámica antigua.
Si uno quiere fuerza bruta, hay 2 tipos de fuerza bruta:
Permuta todas las cosas, luego elige min más alto: O (n!)
Similar a esta implementación, pero en lugar de DP, la ejecución bruta del paso de poblar el mapa indexToIndexOfNextSmallerLeft se ejecutará en O (n ^ 2).
fuente
Necesitamos encontrar el bit 0 más correcto seguido de un 1 y voltear este bit 0 más a la derecha a 1.
por ejemplo, digamos que nuestra entrada es 487, que es 111100111 en binario.
volteamos el 0 más a la derecha que tiene 1 siguiendo
entonces obtenemos 111101111
pero ahora tenemos un 1 adicional y uno menos 0, por lo que reducimos el número de 1 a la derecha del bit flip en 1 y aumentamos el número de 0 bits en 1, produciendo
111101011 - binario 491
fuente
fuente
Aquí está la implementación de Java
Aquí están las pruebas unitarias
fuente
Sé que esta es una pregunta muy antigua, pero aún así no encontré un código fácil en C #. Esto podría ayudar a los chicos que asisten a las entrevistas.
fuente
Implementación muy simple usando Javascript, el siguiente número más alto con los mismos dígitos
Como hay muchos comentarios, es mejor que puedas copiarlo en tu editor de texto. ¡Gracias!
fuente
Hay muchas buenas respuestas, pero no encontré una implementación decente de Java. Aquí están mis dos centavos:
fuente
fuente