LeetCode: 438. Encontrar todos los anagramas en una cadena: análisis y código (Java)

LeetCode — 438. Encuentra todos los anagramas en una cadena [Encuentra todos los anagramas en una cadena] —— Análisis y código [Java]

1. Título

Dada una cadena s y una cadena no vacía p, busque todas las subcadenas de la letra dislexia de p en s, y devuelva el índice inicial de estas subcadenas.

La cadena contiene solo letras minúsculas en inglés, y la longitud de las cadenas s y p no son más de 20100.

Descripción:

  • Las palabras alifáticas se refieren a cadenas con las mismas letras pero con diferentes disposiciones.
  • No se considera el orden en que se emiten las respuestas.

Ejemplo 1:

输入:
s: "cbaebabacd" p: "abc"

输出:
[0, 6]

解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。

Ejemplo 2:

输入:
s: "abab" p: "ab"

输出:
[0, 1, 2]

解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。

Fuente: LeetCode (LeetCode)
Enlace: https://leetcode-cn.com/problems/find-all-anagrams-in-a-string Los
derechos de autor son propiedad de LeetCode . Para reimpresiones comerciales, comuníquese con la autorización oficial. Para reimpresiones no comerciales, indique la fuente.

Dos, análisis y código

1. Ventana corredera

(1) Pensando

Diseñe una ventana deslizante con la misma longitud que la cadena p, muévase de izquierda a derecha en la cadena s y juzgue si las letras en la ventana en cada posición son las mismas que la cadena p.
Para mejorar la eficiencia del juicio, se puede usar un número y una matriz para registrar el mismo número de letras en la ventana actual, y el tipo de letras en la ventana de registro de la cola se puede combinar para mantener rápidamente la ventana.
Cuando encuentre una letra que no existe en la cadena p, puede mover rápidamente el índice izquierdo de la ventana detrás de esa posición.

(2) Código

class Solution {
    
    
    public List<Integer> findAnagrams(String s, String p) {
    
    
        List<Integer> ans = new ArrayList<>();
        if (s.length() == 0 || p.length() == 0)
            return ans;
        
        char[] cs = s.toCharArray();
        char[] cp = p.toCharArray();
        int wLen = p.length();//窗口长度
        int len = 0, index = 0;//窗口中字符个数,窗口首字符位置
        boolean[] hasChar = new boolean[26];//记录p中是否存在该字母
        int[] numChar = new int[26];//记录当前窗口中还需出现各字母个数
        for (int i = 0; i < 26; i++) {
    
    //初始化
            hasChar[i] = false;
            numChar[i] = 0;
        }
        for (int i = 0; i < wLen; i++) {
    
    //记录p中数据
            hasChar[cp[i] - 'a'] = true;
            numChar[cp[i] - 'a']++;
        }
        
        Queue<Character> win = new LinkedList<Character>();
        for (int i = 0; i < s.length(); i++) {
    
    
            if (hasChar[cs[i] - 'a'] == false) {
    
    //出现p中不存在的字母,直接将窗口起点跳到下一字符处
                while (len > 0) {
    
    
                    numChar[win.poll() - 'a']++;
                    len--;
                }
                index = i + 1;
                continue;
            }
            if (numChar[cs[i] - 'a'] > 0) {
    
    //出现p中存在且当前窗口中个数不足的字母
                win.offer(cs[i]);
                numChar[cs[i] - 'a']--;
                len++;
                if (numChar[cs[i] - 'a'] == 0 && len == wLen) {
    
    //此时窗口范围为p的字母异位词的子串
                    ans.add(index);
                    numChar[win.poll() - 'a']++;
                    len--;
                    index++;
                }
                continue;
            }
            while (len > 0 && win.peek() != cs[i]) {
    
    //出现p中存在但当前窗口中个数已达到需求的字母
                numChar[win.poll() - 'a']++;
                len--;
                index++;
            }
            win.poll();
            index++;
            win.offer(cs[i]);           
        }
        
        return ans;
    }
}

(3) Resultados

Tiempo de ejecución: 10 ms, superando al 69,58% de los usuarios
en todas las presentaciones de Java ; consumo de memoria: 40,2 MB, superando al 30,75% de los usuarios en todas las presentaciones de Java.

2. Optimización de la ventana deslizante

(1) Pensando

En el método anterior, los elementos de la cola se organizan de manera ordenada de acuerdo con sus posiciones en la matriz y se puede acceder a ellos directamente a través del subíndice. En este caso, no es necesario crear la entidad Cola y la ventana el rango se marca directamente en la matriz a través del punto de inicio y la longitud para reducir la sobrecarga de mantenimiento de la cola.

(2) Código

class Solution {
    
    
    public List<Integer> findAnagrams(String s, String p) {
    
    
        List<Integer> ans = new ArrayList<>();
        if (s.length() == 0 || p.length() == 0)
            return ans;
        
        char[] cs = s.toCharArray();
        char[] cp = p.toCharArray();
        int wLen = p.length();//窗口长度
        int len = 0, index = 0;//窗口中字符个数,窗口首字符位置
        boolean[] hasChar = new boolean[26];//记录p中是否存在该字母
        int[] numChar = new int[26];//记录当前窗口中还需出现各字母个数
        for (int i = 0; i < 26; i++) {
    
    //初始化
            hasChar[i] = false;
            numChar[i] = 0;
        }
        for (int i = 0; i < wLen; i++) {
    
    //记录p中数据
            hasChar[cp[i] - 'a'] = true;
            numChar[cp[i] - 'a']++;
        }
        
        for (int i = 0; i < s.length(); i++) {
    
    
            if (hasChar[cs[i] - 'a'] == false) {
    
    //出现p中不存在的字母,直接将窗口起点跳到下一字符处
                while (len > 0)
                    numChar[cs[index + --len] - 'a']++;
                index = i + 1;
                continue;
            }
            if (numChar[cs[i] - 'a'] > 0) {
    
    //出现p中存在且当前窗口中个数不足的字母
                numChar[cs[i] - 'a']--;
                len++;
                if (numChar[cs[i] - 'a'] == 0 && len == wLen) {
    
    //此时窗口范围为p的字母异位词的子串
                    ans.add(index);
                    numChar[cs[index++] - 'a']++;
                    len--;
                }
                continue;
            }
            while (len > 0 && cs[index] != cs[i]) {
    
    //出现p中存在但当前窗口中个数已达到需求的字母
                numChar[cs[index++] - 'a']++;
                len--;
            }
            index++;
        }
        
        return ans;
    }
}

(3) Resultados

Tiempo de ejecución: 5 ms, superando al 93,68% de los usuarios
en todas las presentaciones de Java ; consumo de memoria: 39,7 MB, superando al 84,86% de los usuarios en todas las presentaciones de Java.

Tres, otro

Nada.

Supongo que te gusta

Origin blog.csdn.net/zml66666/article/details/112640906
Recomendado
Clasificación