Aprendizaje de algoritmos topológicos

Recientemente, siento que me he encontrado con un cuello de botella al responder las preguntas. En primer lugar, hay un gato y un ratón II para la pregunta diaria. Lo pensé durante 2 horas, pero no sé qué tipo de solución. debe usarse para completar esta pregunta. Al final, solo pude hacer clic en secreto en la solución oficial del problema. Esta vez, el método proporcionado por la solución oficial del problema es diferente de la programación dinámica anterior, la recursividad, la codicia, etc. Esta vez el algoritmo oficial es un algoritmo topológico, vi que el nombre es alto, ¿algoritmo superior? Pero después de leer la solución, todavía no podía entenderla, así que cambié el tema a Alien Dictionary. También pensé en este problema durante mucho tiempo, pero no lo logré. Al final, la solución que más vi en las soluciones de otras personas fue el algoritmo topológico. Esta vez fui a Internet para buscar la información y las soluciones de los algoritmos de topología.


Este artículo se ha colocado en la caja de borrador y no tengo tiempo para escribirlo. No esperaba que la pregunta diaria de hoy fuera este diccionario alienígena. ¡Date prisa y termínalo! ! !


Ya hay mucha información sobre algoritmos topológicos en Internet. Aquí me gustaría decir que todavía tenía obstáculos cuando estaba aprendiendo algoritmos topológicos. En primer lugar, el algoritmo de topología es más fácil de entender, en resumen, es como un árbol de habilidades en un juego. Por ejemplo, solo puede señalar la habilidad de expansión 2 después de la habilidad 1 después de señalar la 1, y puede señalar habilidades posteriores solo después de señalar las habilidades 1, 2 y 3. El algoritmo aquí también es el mismo, y las condiciones previas deben completarse antes de que se puedan hacer las siguientes cosas. Esto es similar a ordenar. Por ejemplo, organice 1 y 3 antes de clasificar 2, luego el orden es 1, 3, 2 (o 3, 1, 2, aquí no se requiere el orden de 1 y 3, por lo que el resultado topológico la clasificación puede ser más que una especie de). Entonces, cuando nos encontramos con tales problemas, ¿cómo debemos comenzar? (por ejemplo, diccionario alienígena)

Lo primero que tenemos que hacer es construir un gráfico. La clasificación topológica es un gráfico acíclico dirigido. Dirigido es fácil de entender. ¿Qué es acíclico? Es decir, la relación entre números y números no puede ser mutua. Por ejemplo, la condición para desbloquear la habilidad 3 es hacer clic primero en la habilidad 2, pero la habilidad 2 le dice que debe hacer clic en la habilidad 3 antes de poder hacer clic en ella. Infinito bucle, aquí no hay orden, lo que también corresponde a la situación en la que el orden de las preguntas es ilegal. Aquí utilizo dos diccionarios, uno para construir el grado, es decir, en cuántas habilidades anteriores hay que hacer clic para desbloquear la habilidad, y el otro para construir el valor previo, es decir, cuántas habilidades tienen una condición de desbloqueo menos después haciendo clic en esta habilidad. Con estos dos diccionarios, la composición depende de los requisitos específicos.El siguiente es el código del diccionario alienígena.

static Dictionary<char, HashSet<char>> val = new Dictionary<char, HashSet<char>>();//前置值
    static Dictionary<char, int> du = new Dictionary<char, int>();//度
    public static string AlienOrder(string[] words)
    {
        int n = words.Length;
        if (n == 0) return "";
        AlienOrderM1(words[0]);
        for (int i = 1; i < n; i++)
        {
            AlienOrderM1(words[i]);
            if (!AlienOrderM1(words[i - 1], words[i])) return "";
        }
        var q = new Queue<char>();
        foreach (var a in du)
        {
            if (a.Value == 0) q.Enqueue(a.Key);
        }
        var ans = new StringBuilder();
        while (q.Count > 0)
        {
            char a = q.Dequeue();
            ans.Append(a);
            foreach (var item in val[a])
            {
                du[item]--;
                if (du[item] == 0) q.Enqueue(item);
            }
        }
        return ans.Length == du.Count ? ans.ToString() : "";
    }
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="a"></param>
    public static void AlienOrderM1(string a)
    {
        foreach (var item in a)
        {
            if (!val.ContainsKey(item)) { val.Add(item, new HashSet<char>()); du.Add(item, 0); }
        }
    }
    /// <summary>
    /// 构图
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static bool AlienOrderM1(string a, string b)
    {
        for (int i = 0; i < a.Length && i < b.Length; i++)
        {
            if (a[i] != b[i])
            {
                if (val[a[i]].Add(b[i]))
                {
                    du[b[i]]++;
                }
                return true;
            }
        }
        if (a.Length > b.Length) return false;
        return true;
    }

Finalmente, lo que tenemos que hacer después de construir el gráfico es ver si es un gráfico de bucle cerrado, que sea un gráfico de bucle cerrado depende de la longitud de la cadena construida al final y la cantidad de caracteres que hayan aparecido. en el título. Si es el mismo, significa que cada Si se eliminan todos los caracteres, significa que no hay bucle. Si diferentes personajes tienen un bucle cerrado, no se pueden eliminar por completo, y esto no cumple las condiciones del tema Simplemente devuelva una cadena vacía. 


Aquí publico la respuesta oficial de Likou:

Esta pregunta es un problema de clasificación topológica. Las letras y el orden de las letras en el diccionario alienígena pueden considerarse como un gráfico dirigido, y el orden del diccionario es una disposición de todas las letras, lo que satisface que el orden de la letra inicial y la letra final de cada borde dirigido esté dispuesto. con estas dos letras en el mismo orden, esta disposición es el género topológico del grafo dirigido.

Solo cuando no hay ciclo en el grafo dirigido, hay una clasificación topológica, y puede haber más de una clasificación topológica. Si hay un ciclo en el grafo dirigido, no hay una permutación satisfactoria de las letras en el anillo, por lo que no hay clasificación topológica.

Cuando se utiliza la clasificación topológica para resolver, cada letra del diccionario alienígena se considera un nodo y la relación de orden entre las letras se considera un borde dirigido. Para dos palabras adyacentes en el diccionario alienígena, atraviese de izquierda a derecha al mismo tiempo, cuando se encuentra la primera letra que no es la misma, existe una relación de orden entre las dos letras en esta posición.

No existe orden alfabético legal en los dos casos siguientes:

Hay un anillo que consta de al menos 2 letras en la relación de secuencia entre letras, por ejemplo, palabras = ["a", "b", "a"];

Dos palabras adyacentes cumplen que la palabra siguiente es el prefijo de la palabra anterior, y la longitud de la palabra siguiente es menor que la longitud de la palabra anterior, por ejemplo, palabras=["ab", "a"].

En todos los demás casos, existe un orden alfabético legal y se puede utilizar la clasificación topológica para obtener un orden lexicográfico.

La ordenación topológica se puede implementar utilizando la búsqueda primero en profundidad o la búsqueda primero en amplitud.Los dos métodos de implementación siguientes se presentan respectivamente.

Método 1: clasificación topológica + búsqueda primero en profundidad
La idea general de usar la búsqueda primero en profundidad para implementar la clasificación topológica es: para un nodo específico, si se han buscado todos los nodos adyacentes del nodo, el nodo también se buscará A nodo que se coloca delante de todos sus vecinos en una ordenación topológica. Los nodos adyacentes de un nodo se refieren a los nodos a los que se puede llegar desde el nodo a través de un borde dirigido.

Dado que el orden de clasificación topológica es opuesto al orden de finalización de la búsqueda, es necesario utilizar una pila para almacenar todos los nodos que se han buscado. En el proceso de búsqueda primero en profundidad, se debe mantener el estado de cada nodo. El estado de cada nodo puede tener tres situaciones: "no visitado", "visitando" y "visitado". Inicialmente, el estado de todos los nodos es "sin visitar".

En cada ronda de búsqueda, seleccione aleatoriamente un nodo uu "no visitado" y comience la búsqueda en profundidad desde el nodo uu. Actualice el estado del nodo uu a "Visitante", para cada nodo vv adyacente al nodo uu, juzgue el estado del nodo vv, realice las siguientes operaciones:

Si el estado del nodo vv es "no visitado", continúe buscando el nodo vv;

Si el estado del nodo vv es "visitante", se encuentra un ciclo en el grafo dirigido, por lo que no hay clasificación topológica;

Si el estado del nodo vv es "visitado", entonces el nodo vv se ha buscado y se ha puesto en la pila, y el nodo uu no se ha puesto en la pila, por lo que el orden topológico del nodo uu debe estar delante del nodo vv, y no se requiere ninguna operación.

Cuando el estado de todos los nodos adyacentes del nodo uu sea "visitado", actualice el estado del nodo uu a "visitado" y coloque el nodo uu en la pila.

Después de que se hayan visitado todos los nodos, si no se encuentra ningún ciclo en el gráfico dirigido, hay una clasificación topológica, y el orden de todos los nodos desde la parte superior de la pila hasta la parte inferior de la pila es la clasificación topológica.

En términos de implementación, dado que cada nodo es una letra, se puede usar una matriz de caracteres en lugar de una pila.Cuando se empuja un nodo a la pila, cada letra se completa en la matriz de caracteres en orden de atrás hacia adelante. Una vez que se han visitado todos los nodos, la matriz de caracteres se convierte en una cadena, que es el orden del diccionario.

Solución oficial de Leetcode https://leetcode.cn/problems/Jf1JuT/solution/wai-xing-wen-zi-dian-by-leetcode-solutio-to66/

Supongo que te gusta

Origin blog.csdn.net/X1iaoXu666/article/details/124756291
Recomendado
Clasificación