La prueba escrita más popular: use la ventana deslizante para resolver la coincidencia de cadenas

Introducción al proyecto

  • Este proyecto descompone las preguntas comunes de entrevistas escritas de las principales fábricas, rastrea la fuente hasta los principios de implementación subyacentes de las estructuras de datos y los algoritmos, y sabe cuáles son.
  • Establezca un sistema de estructura de conocimiento para una búsqueda fácil y dé la bienvenida a más amigos con ideas afines a unirse al proyecto AlgorithmPractice (los problemas y las solicitudes de extracción son bienvenidos).

Que es una ventana corrediza

  • En un recorrido tanto como sea posible, busque el patrón coincidente de la cadena de destino en la cadena de origen.

Siete soluciones a cinco preguntas

Inicio del texto

1. Coincidencia de secuencia

  • Dada una cadena de origen, proporcione una cadena de destino para ver si hay una secuencia de cadenas de destino en la cadena de origen, por ejemplo:
    • Caso positivo
      • Cadena de origen: "1a2b3c4d",
      • Cadena de destino: "1234"
      • Obviamente, hay una secuencia de cadenas de destino en la cadena de origen.
    • Contra-caso:
      • Cadena de origen: "1a2b3cd",
      • Cadena de destino: "1234"
      • Obviamente, no hay una secuencia de cadenas de destino en la cadena de origen.
    • Solución: debido a que nuestro propósito es muy simple, solo necesita decirme si la memoria no existe, verdadera o falsa, por lo que a través de un bucle, el puntero de origen apunta a la posición de la cadena de origen y el puntero de destino apunta a la posición de la cadena de destino. Los dos punteros funcionan sincrónicamente, y finalmente Simplemente juzgue si el puntero de destino es igual a la longitud de la cadena de destino. Por supuesto, si esta pregunta se cambia a la secuencia de la parte común más larga de las dos, debe ser procesada por la solución LCS. El código fuente completo de esta pregunta: SequenceExist . Además de este método, también hay un método llamado preprocesamiento de cadenas : el preprocesamiento de cadenas resuelve el problema de coincidencia de cadenas
    • Código principal:
while (sourcelength < source.length() && targetlength < target.length()){
    
    
    if(targetchar[targetlength] == sourcechar[sourcelength]){
    
    
        targetlength++;
    }
        sourcelength++;
}
return targetlength == target.length();

2. Subcadena de cobertura mínima

  • Dada una cadena de origen, proporcione una cadena de destino para ver si hay una secuencia de la cadena de destino en la cadena de origen, especialmente: para esta secuencia, permitimos que exista desordenada en la cadena de origen. Pero si solo se trata de un juicio de existencia, entonces se puede hacer una lista o un mapa de hash. Almacene la cadena de destino en la lista, recorra la cadena de origen, elimine el carácter de la lista, cuando la lista esté vacía, devuelva verdadero, de lo contrario devuelva falso .
  • Pedimos ir más allá. Suponiendo que hay varios caracteres en la cadena de destino en la cadena de origen, encuentre el intervalo más pequeño que contenga todos los caracteres en la cadena de destino, como:
    • Caso positivo
      • Cadena de origen: "2a41b156d3c24d",
      • Cadena de destino: "1234"
      • Obviamente, hay una secuencia de cadenas de destino fuera de orden en la cadena de origen, pero el intervalo de la subcadena de cobertura más pequeña es "156d3c24".
    • Contra-caso:
      • Cadena de origen: "1a2b3cd",
      • Cadena de destino: "1234"
      • Obviamente, no hay una secuencia de cadenas de destino en la cadena de origen.
    • Solución: Este problema debe considerarse desde la perspectiva de la ventana deslizante, código fuente completo: MinimumWindowSubstring .
    • Código principal:
//右侧窗口扩张
while (right < source.length()) {
    
    
    char cright = source.charAt(right);
    right++;
    if (targetMap.containsKey(cright)) {
    
    
        int num = windowsMap.containsKey(cright) ? windowsMap.get(cright) + 1 : 1;
        windowsMap.put(cright, num);
        if (windowsMap.get(cright) == targetMap.get(cright)) {
    
    
            count++;
        }
    }
    //判断左侧窗口是否进行收缩,注意此处是个循环,不是if
    while (count == targetMap.size()) {
    
    

        //更新数据
        if (right - left < subLength) {
    
    
            begin = left;
            subLength = right - left;
        }
        char cleft = source.charAt(left);
        left++;
        if (targetMap.containsKey(cleft)) {
    
    
            if (windowsMap.get(cleft) == targetMap.get(cleft)) {
    
    
                count--;
            }
            windowsMap.put(cleft, windowsMap.get(cleft) - 1);
        }
    }
}

3. La subcadena de cadena contiene detección

  • Descripción: Para una cadena de origen y una cadena de destino determinadas, compruebe si hay una cadena de destino en la cadena de origen, que sea diferente de la subcadena de cobertura mínima que acaba de hacer. Esta vez es una cadena, no una secuencia. como:
    • Caso positivo
    • Cadena de origen: "cd63412asd",
    • Cadena de destino: "1234"
    • Obviamente, la cadena de destino existe desordenada en la cadena de origen.
  • Contra-caso:
    • Cadena de origen: "123c4d",
    • Cadena de destino: "1234"
    • Obviamente, no hay una cadena continua de caracteres de destino en la cadena de origen.
  • Solución: Este problema también debe considerarse desde la perspectiva de la ventana deslizante. No es más que juzgar si la ventana es consistente con la cadena de destino. El código fuente completo: PermutationinString .
  • Código principal:
if (right - left == target.length()) {
    
    
    if (count == targetMap.size()) {
    
    
        return true;
    }
    char cleft = source.charAt(left);
    if(windowsMap.containsKey(cleft)){
    
    
        windowsMap.put(cleft, windowsMap.get(cleft) - 1);
        count--;
    }
    left++;
}

4. Encuentra todas las palabras disfóricas de letras

  • Descripción: para una cadena de origen y una cadena de destino determinadas, si hay varias cadenas de destino en la cadena de origen, se devuelven sus direcciones reales. como:
    • Caso positivo
    • Cadena de origen: "cd63412as2314d",
    • Cadena de destino: "1234"
    • Obviamente, la cadena de destino existe desordenada en la cadena de origen, pero las posiciones son [3,9] respectivamente.
  • Contra-caso:
    • Cadena de origen: "123c4d",
    • Cadena de destino: "1234"
    • Obviamente, no hay una cadena continua de caracteres de destino en la cadena de origen.
  • Solución: Este problema también debe considerarse desde la perspectiva de la ventana deslizante. Al igual que la detección de inclusión de subcadenas de cadenas, no es más que varias listas para almacenar la dirección inicial de cada cadena coincidente. El código fuente completo: FindallAnagrams .
  • Código principal:
if (right - left + 1 == target.length()) {
    
    
    //符合条件,进行存入
    if (point == targetMap.size()) {
    
    
        count.add(left);
        //1号位
    }
    //缩小窗口
    char cleft = source.charAt(left);
    if(windowsMap.containsKey(cleft)){
    
    
        windowsMap.put(cleft, windowsMap.get(cleft) - 1);
        point--;//point--只能放在此处,不可以放在 1号位
    }
    left++;
}

5. La longitud de subcadena no repetitiva más larga

  • Descripción: dada una cadena, busque la cadena única más larga, como:
    • Caso positivo
      • Cadena de origen: "aassddffgghh",
      • La longitud de subcadena no repetitiva más larga: 2
      • Obviamente, any as, o sd, df, fg, gh, tiene una longitud de 2.
    • Solución: Hay dos soluciones para este problema, el método de cubo, o desde la perspectiva de la ventana deslizante, el código fuente completo del método de cubo y el método de ventana deslizante: LNRSubstring .
    • El código principal del método del cubo:
for (int begin = 0, j = 0; j < s.length(); j++) {
    
    
    //找出子串起始位置,通过重复值来判断
    begin = Math.max(bottle[s.charAt(j)], begin);
    //更新记录值
    count = Math.max(count, j - begin + 1);
    //更新桶序号对应的子串起始位置
    bottle[s.charAt(j)] = j + 1;
}
  • El código principal de la ventana deslizante.
while(right < s.length()){
    
    
    Character c = s.charAt(right);
    if(!windows.containsKey(c)){
    
    
        windows.put(c,right);
        count = windows.size() > count ? windows.size() : count;
    }else {
    
    
        while (left < right && windows.containsKey(c)){
    
    
            windows.remove(s.charAt(left));
            left++;
        }
        windows.put(c,right);
    }
    right++;
}

Supongo que te gusta

Origin blog.csdn.net/ljfirst/article/details/106972100
Recomendado
Clasificación