Se le proporciona una matriz A de k valores que contienen valores int en orden ordenado (asec). Encuentre los valores de k superiores (asec) que pueden ser el número de la matriz A, o la suma de dos números de A o la suma de tres números de A.?

Explicación:

La solución a este problema será muy parecida a la operación de fusión de tipo de fusión. Lo que eso significa es que tendremos un conjunto de listas ordenadas que queremos fusionar. Seleccionaremos los elementos más pequeños de esas listas hasta que tengamos k elementos. Esa será nuestra solución.

Primero, ¿cuáles son las listas que necesitamos fusionar? Necesitamos el más pequeño de:

  1. La lista original de números en orden ascendente.
  2. La lista producida por todas las combinaciones de 2 elementos de la lista original en orden ascendente
  3. La lista producida por todas las combinaciones de 3 elementos de la lista original en orden ascendente

Ya tenemos la primera lista, por lo que solo necesitamos generar la segunda y la tercera lista. El enfoque ingenuo sería generar todos los valores en las listas 2 y 3 y luego ordenar los valores. Sin embargo, podríamos hacerlo mejor que eso. Si pensamos en la operación de fusión que estamos haciendo, realmente necesitamos obtener solo el elemento más pequeño de cada lista por iteración. Cada vez que seleccionamos el elemento más pequeño, necesitamos obtener el siguiente elemento más pequeño. Tal vez podamos hacer una función para obtener valores sucesivos de la lista 2 y la lista 3 en tiempo constante.

Sin embargo, si eso fuera posible, podríamos generar una lista ordenada de todas las sumas por pares en tiempo [matemático] \ Theta (n ^ 2) [/ matemático]. La solución más conocida para generar todas las sumas por pares de una lista en orden ordenado es [matemática] \ Theta (n ^ 2 \ lg n) [/ matemática] (vea el Problema 41: Ordenar X + Y (Sumas por parejas). de una manera de hacerlo, ¡hágamelo saber! 🙂 Para los fines de una entrevista, no espero que invente avances en la informática. Por lo tanto, iremos con los ingenuos [matemáticos] \ Theta (n ^ 2 \ lg n) [/ math] solución, que es generar todos los pares y luego ordenar cada par por su suma. Podemos generar todos los pares en [math] \ Theta (n ^ 2) [/ math] time, y nosotros puede ordenarlos en [matemáticas] \ Theta (n ^ 2 \ lg n) [/ matemáticas] tiempo (ya que [matemáticas] n ^ 2 \ lg n ^ 2 [/ matemáticas] es lo mismo que [matemáticas] 2 n ^ 2 \ lg n [/ math]), dándonos nuestra lista ordenada de sumas por pares en el tiempo [math] \ Theta (n ^ 2 \ lg n) [/ math]. Del mismo modo, podemos generar una lista ordenada de todos los 3 elementos sumas en [matemáticas] \ Theta (n ^ 3 \ lg n) [/ matemáticas] tiempo.

Dadas las listas 1, 2 y 3, podemos seleccionar repetidamente el elemento mínimo de las listas 1, 2 o 3 hasta que tengamos elementos [math] k [/ math]. Los elementos [math] k [/ math] que seleccionamos serán nuestra solución.

El tiempo de ejecución general de esta solución es [matemática] \ Theta (n ^ 3 \ lg n) [/ matemática] (suponiendo que [matemática] k [/ matemática] no puede ser mayor que el tamaño de la concatenación de listas 1 , 2 y 3, que es una suposición razonable dado que queremos tener valores reales para devolver).

Notas:

Mi solución resuelve el caso (b) de su enunciado del problema. Por lo tanto, también resuelve el caso (a). No puedo pensar en una forma más eficiente de resolver el problema si necesito satisfacer solo el caso (a), al menos en términos de complejidad asintótica.

Si bien la solución descrita anteriormente es la mejor solución asintótica que se me ocurre, eso no significa que no haya soluciones más eficientes. Sin embargo, cualquier otra solución seguirá teniendo el mismo tiempo de ejecución asintótico (a menos que se idee una mejor solución para el problema abierto que mencioné anteriormente).

Pensemos en cómo podría ser una solución más eficiente. Suponga que [math] k [/ math] es lo suficientemente pequeño como para saber que no necesitaremos generar las listas 1, 2 o 3 en su totalidad. Entonces podríamos truncar esas listas según sea necesario para ahorrar tiempo de ejecución

Truncar la lista 1 es trivial. Truncar las listas 2 y 3 y mantenerlas ordenadas es un poco más difícil. Una posible solución que planteo sería hacer algo similar a la búsqueda binaria. Por ejemplo, supongamos que solo queremos los 5 elementos más pequeños de la lista 2. Podríamos comenzar con dos punteros en la lista 1, uno en el índice 0 y otro en el índice 1. Luego podríamos incrementar un puntero en 1 y disminuir el otro puntero como tantos elementos como sea posible de modo que la suma de los valores señalados por los dos punteros no vaya por debajo de la suma anterior. (Podemos descubrir cuántos elementos para disminuir el otro puntero con una búsqueda binaria modificada). Por lo tanto, podemos encontrar cada elemento sucesivo en la lista 2 en [math] \ Omega (\ lg n) [/ math] time. Sin embargo, debemos tener cuidado si queremos evitar que los punteros se muevan en ciclos. Este método todavía tiene un tiempo de ejecución de [math] \ Theta (n ^ 2 \ lg n) [/ math] si lo usamos para generar todas las sumas por pares [math] n ^ 2 [/ math], pero tiene el beneficio adicional de que podemos tomar el elemento más pequeño paso a paso. Si solo necesitamos algunos elementos de las listas 2 y 3, un método como el que acabo de describir podría ser más ideal.

Implementación de Java:

import java.util.Arrays; public class KSmallestWithCombosOf2And3 { public static void main(String[] args) { int[] A = { 3, 4, 5, 15, 19, 20, 25 }; Integer[] B = KSmallestWithCombosOf2And3(A, 63); System.out.print("[ "); for (int i = 0; i < B.length; i++) { String next = (i == B.length - 1) ? " " : ", "; System.out.print(B[i] + next); } System.out.println("]"); } public static Integer[] KSmallestWithCombosOf2And3(int[] list, int k) { if (k < 1 || list == null || list.length == 0) { return new Integer[0]; } Integer[] result = new Integer[k]; int[][] lists = new int[][] { list, getCombosOf2(list), getCombosOf3(list) }; int[] ptrs = { 0, 0, 0 }; for (int i = 0; i < k; i++) { int min = 0; int minIndex = 0; boolean minAssigned = false; for (int j = 0; j < 3; j++) { if (ptrs[j] < lists[j].length && (lists[j][ptrs[j]] < min || !minAssigned)) { min = lists[j][ptrs[j]]; minIndex = j; minAssigned = true; } } if (minAssigned) { ptrs[minIndex]++; result[i] = min; } else { result[i] = null; } } return result; } public static int[] getCombosOf2(int[] list) { int n = list.length; int numCombos = n * (n - 1) / 2; int[] result = new int[numCombos]; for (int i = 0, c = 0; i < n; i++) { for (int j = 0; j < i; j++, c++) { result[c] = list[i] + list[j]; } } Arrays.sort(result); return result; } public static int[] getCombosOf3(int[] list) { int n = list.length; int numCombos = n * (n - 1) * (n - 2) / 6; int[] result = new int[numCombos]; for (int i = 0, c = 0; i < n; i++) { for (int j = 0; j < i; j++) { for (int k = 0; k < j; k++, c++) { result[c] = list[i] + list[j] + list[k]; } } } Arrays.sort(result); return result; } } 

Salida:

  [3, 4, 5, 7, 8, 9, 12, 15, 18, 19, 19, 20, 20, 22, 22, 23, 23, 23, 24, 24, 24,
 25, 25, 26, 27, 27, 28, 28, 28, 29, 29, 30, 32, 33, 34, 34, 35, 37, 38, 38, 39,
 39, 39, 40, 40, 42, 43, 43, 44, 44, 44, 45, 45, 47, 48, 48, 49, 49, 50, 54, 59,
 60, 64] 

No sé si existe una mejor solución para el caso a, supongo que no existe una mejor solución para el caso a.

En primer lugar, observe que no necesitamos toda la lista ordenada de (A [p] + A [q] + A [r]), 1 <= p, q, r <= k, solo necesitamos el Elementos "first-k" de las listas O (k ^ 3). Generar las listas completas de triple suma y ordenarlas requiere O (k ^ 3 lg k) que definitivamente no cabe en la respuesta del entrevistador.

En lugar de generar la lista completa de elementos O (k ^ 3), deberíamos generar un sucesor solo cada vez e iterar exactamente k veces.

Por ejemplo, el elemento mínimo es trivial:
A [1] + A [2] + A [3], su sucesor también es trivial: A [1] + A [2] + A [4], el siguiente sucesor es el más pequeño de los candidatos {A [1] + A [2] + A [5], A [2] + A [3] + A [4]}, aquí está la parte clave: supongamos que el siguiente sucesor es A [1] + A [2] + A [ 5], entonces los candidatos sucesores se convierten en {A [2] + A [3] + A [4], A [1] + A [2] + A [6], A [1] + A [3] + A [5]}.

Supongamos que A es la matriz de entrada, M son los elementos más pequeños de i de triple suma de A, S es el conjunto de posibles candidatos sucesores.

FindSmallestKTripleSum (A)
M <- conjunto vacío
S <- conjunto vacío
insertar tupla (1,2,3) en S # indica A [1] + A [2] + A [3]
para i = 0 a k-1 do
sucesor (p, q, r) <- popSmallestElement (S)
empujar (p, q, r) a M
insertar (p + 1, q, r) en S
inserte (p, q + 1, r) en S
inserte (p, q, r + 1) en S
fin para
devolver M

Es obvio ver si implementamos S usando un montón mínimo, tanto insertar en S como popSmallestElement (S) lleva tiempo O (lg k), ya que el tamaño de S es O (3k) = O (k). Además, la iteración lleva k veces, la complejidad del tiempo es O (k lg k)

Tenga en cuenta que la implementación de S requiere algunos detalles ignorados anteriormente, como cuando se inserta una tupla de 3 (p, q, r), debemos filtrar la ilegal (como p = q o q = r o fuera de k), también deberíamos hacer que S sea único.

Se puede aplicar a la suma por pares o incluso a la suma cuadrática o cualquier otro número, todo lleva tiempo O (k lg k). Entonces, por fin podemos fusionar tres listas de elementos k y encontrar la k más pequeña en el tiempo O (k lg k), por lo que la complejidad general sigue siendo O (k lg k).

Puede desarrollar un algoritmo para evitar el paso de fusionar las tres listas.
FindB (A)
B <- conjunto vacío
S <- conjunto vacío
inserte (1), (1,2), (1,2,3) en S
para i = 0 a k-1 do
sucesor <- popSmallestElement (S)
empujar sucesor en B
si sucesor = (p) entonces
insertar (p + 1) en S
si sucesor = (p, q) entonces
inserte (p + 1, q), (p, q + 1) en S
si sucesor = (p, q, r) entonces
inserte (p + 1, q, r), (p, q + 1, r), (p, q, r + 1) en S
fin para
volver B

Una última cosa, dado que este es un problema planteado en la entrevista de programación, puede notar que la entrada dada de A son “enteros”. Entonces puede preguntarle al entrevistador si los rangos de enteros son relativamente pequeños.

Si la respuesta es positiva, suponga que los rangos enteros se encuentran en O (w), puede obtener fácilmente una solución pseudo polinomial en complejidad temporal O (w + k)

More Interesting

¿Cuál es su opinión sobre las entrevistas de programación?

¿Cómo se puede obtener un puntaje de 3+ de manera consistente en cada ronda de entrevistas de Google?

¿Hay algún blog sobre preguntas de entrevistas de programación?

¿Cómo se convirtieron las preguntas sobre estructuras de datos y algoritmos en la norma para las entrevistas tecnológicas?

C ++ (lenguaje de programación): ¿Cómo puedo usar BST para encontrar el elemento mayoritario en una matriz sin clasificar?

¿Aproximadamente cuánto tiempo se espera que pasen los candidatos para trabajos de programación en tareas de programación para llevar a casa?

Tengo una matriz de números del 1 al 1000000, necesito obtener el tiempo que toma cada elemento de la matriz para converger a 1 sin ningún cálculo repetido. ¿Cómo debo resolver este problema?

Cómo usar de manera óptima los seis meses que tengo para mejorar en Python

¿Qué temas debo estudiar en Java para limpiar entrevistas de programación?

¿Qué tipo de preguntas hace Interviewstreet en la ronda telefónica?

¿Qué debo esperar en una entrevista de ingeniero de software en Google y cómo debo prepararme?

¿Por qué las grandes compañías tecnológicas como Google / Amazon / FB no hacen que sus entrevistas de codificación de pantalla de teléfono sean más estrictas?

¿Cuáles son algunas de las posibles razones por las que un entrevistador rechazaría a un entrevistado si el entrevistado contesta correctamente todas las preguntas prácticas del examen?

¿Qué tipo de preguntas se hacen en la sección de programación de Amdocs (que consta de 7 preguntas de codificación) en la primera ronda de aptitud?

Si hay una matriz que contiene N números, cuyo rango es de 1 a N + 1, y solo puedo usar el espacio O (1) y no puedo modificar la matriz, ¿puedo encontrar cualquier número repetido no peor que O (NlogN) ¿hora?