Cadena de entrenamiento del algoritmo elemental LeetCode (Completado)

Introducción

Anterior: Matriz de entrenamiento de algoritmos elementales LeetCode

Siguiente: Lista vinculada al entrenamiento del algoritmo primario de LeetCode

Originalmente quería comenzar con el nivel principiante e intermedio y los algoritmos de entrevistas corporativas, pero al final optamos por comenzar desde lo básico, porque no cepillamos preguntas con el propósito de cepillar preguntas, sino ejercitar una especie de algoritmo pensando en el proceso de cepillado de preguntas, después de mucho entrenamiento. Forme una visión única del algoritmo, cultive la sensibilidad al algoritmo, vea el problema, un plan para resolver el problema puede aparecer en el cerebro y, lentamente, genere confianza desde el principio, y esto también es para el complejo algoritmo detrás Sentar las bases para ideas de resolución de problemas.

Introducción al algoritmo primario de LeetCode

Si también quieres entrenar tu propio pensamiento algorítmico, también puedes unirte a mí, comenzando desde el algoritmo elemental, inicia tu viaje del algoritmo: algoritmo elemental .

Un poco de su propio pensamiento: no mire la respuesta después de leer la pregunta y luego recite la pregunta, de modo que la memoria del algoritmo implementado no sea fuerte, debe tener su propio pensamiento; y no escriba sobre IDEA al principio, Asegúrese de intentar escribirlo en la pizarra proporcionada por leetCode y finalmente colóquelo en IDEA para ver si hay algún problema, a fin de consolidar su uso y competencia básica de API; otro punto es ser audaz, no el costo de prueba y error en la entrevista Baja, intenta incorporar nuestras ideas al código.

Debido a problemas de espacio, el blog solo enumera ejemplos y sus propias respuestas de resolución de problemas. Para obtener más detalles, puede hacer clic directamente en el tema para ver.

Cuerda inversa

Escribe una función cuya función sea invertir la cadena de entrada. La cadena de entrada se da en forma de una matriz de caracteres char [].
No asigne espacio adicional a otra matriz, debe modificar la matriz de entrada en su lugar y usar O (1) espacio adicional para resolver este problema.
Puede suponer que todos los caracteres de la matriz son caracteres imprimibles en la tabla de códigos ASCII.

Ejemplo 1:
Entrada: ["h", "e", "l", "l", "o"]
Salida: ["o", "l", "l", "e", "h"]

Ejemplo 2:
Entrada: ["H", "a", "n", "n", "a", "h"]
Salida: ["h", "a", "n", "n", " a "," H "]

class Solution {
    public void reverseString(char[] s) {
        for(int i = 0;i < s.length / 2;i++){
            char temp = s[i];
            s[i] = s[s.length - 1 - i];
            s[s.length - 1 -i] = temp;    
        }
    }
}

Tiempo de ejecución: 1 ms
Consumo de memoria: 46,5 MB

No hay nada que decir sobre esto antes de cambiar la matriz int de esta manera.

Inversión de enteros

Dado un entero de 32 bits con signo, es necesario invertir los dígitos de cada uno de los números enteros.
Ejemplo 1:
Entrada: 123
Salida: 321

Ejemplo 2:
Entrada: -123
Salida: -321

Ejemplo 3:
Entrada: 120
Salida: 21
Nota:
Suponiendo que nuestro entorno solo puede almacenar el siguiente entero de 32 bits con signo, el rango de valores es
[- 2 31, 2 31 - 1] [−2 ^ {31}, 2 ^ {31} - 1][ - 23 1 ,23 1 -1]. De acuerdo con esta suposición, si el entero se desborda después de la inversión, devuelve 0.

El primer método es muy ineficiente por sí mismo.

class Solution {
    public int reverse(int x) {
      boolean isMinusNum = x < 0;
        String s = String.valueOf(Math.abs(x));
        StringBuilder sb = new StringBuilder(s);
        sb.reverse();
         Long aLong;
        try{
             aLong = isMinusNum ? -Long.valueOf(sb.toString()) : Long.valueOf(sb.toString());
        } catch(Exception e){
            return 0;
        }
       
        if (aLong > Integer.MAX_VALUE || aLong < Integer.MIN_VALUE) return 0;
        return aLong.intValue();
    }
}

Tiempo de ejecución: 4 ms
Consumo de memoria: 37,2 MB

El segundo método analiza la respuesta inteligentemente tomando el resto y dividiendo una vez para obtener el resto multiplicado por 10 y acumulando, y el examen físico determina directamente el tamaño de revoluciones en el medio.

class Solution {
    public int reverse(int x) {

        int rev = 0;
        while (x != 0) {
            int tail = x % 10;
            x /= 10;

            if (rev < Integer.MIN_VALUE / 10 || (rev == Integer.MIN_VALUE / 10 && tail < Integer.MIN_VALUE % 10)) {
                return 0;
            }

            if (rev > Integer.MAX_VALUE / 10 || (rev == Integer.MAX_VALUE / 10 && tail > Integer.MAX_VALUE % 10)) {
                return 0;
            }

            rev = rev * 10 + tail;
        }
        return rev;
    
    }
}

Tiempo de ejecución: 1 ms
Consumo de memoria: 37,2 MB

El primer carácter único de la cadena

Dada una cadena, busque su primer carácter único y devuelva su índice. Si no existe, se devuelve -1.
Ejemplo:

s = "leetcode"
devuelve 0

s = "loveleetcode"
devuelve 2
consejos: puede asumir que la cadena contiene solo letras minúsculas.

class Solution {
    public int firstUniqChar(String s) {
        int[] locates = new int[26];
        
        for(int i = 0;i<s.length();i++){
            int num = s.charAt(i) - 'a';
            locates[num] ++;
        }
        
        for(int i = 0;i<s.length();i++){
           int num= s.charAt(i) -  'a';
           if(locates[num] == 1){
               return i;
           }
        }
        
        return -1;
    }
}

Tiempo de ejecución: 7 ms
Consumo de memoria: 40,3 MB La
primera idea es esta, definir una matriz int de tamaño 26, primero atravesar la cadena y calcular la distancia de la letra en comparación con la 'a' en la matriz de 26 tamaños. Posición y, a continuación, recorra el número de posición correspondiente +1.
Después de atravesarlo, se considera que regresa siempre que aparezca una vez en la matriz int de tamaño 26.

También hay una forma inteligente de funcionar más rápido.

Recorra 26 letras minúsculas en inglés, use indexOf y lastIndexOf de la cadena para determinar si la primera y la última aparición del carácter son consistentes, lo que indica que solo aparecen una vez, y luego busque el más pequeño de estos índices.

class Solution {
    public int firstUniqChar(String s) {
       int firstUniqIndex = s.length();
       for(char i = 'a';i<='z';i++) {
           int index = s.indexOf(i);
           if(index != -1 && index == s.lastIndexOf(i)){
               firstUniqIndex = Math.min(firstUniqIndex,index);
           }
       }
        return firstUniqIndex == s.length() ? -1 : firstUniqIndex;
    }
}

Tiempo de ejecución: 2 ms
Consumo de memoria: 40,2 MB

Variantes de letras válidas

Dadas dos cadenas s y t, escribe una función para determinar si t es un anagrama de s.
Ejemplo 1:
Entrada: s = "anagrama", t = "nagaram"
Salida: verdadera

Ejemplo 2:
Entrada: s = "rata", t = "coche"
Salida: falso
Nota:
Puede asumir que la cadena contiene solo letras minúsculas.
Avanzado:
¿Qué pasa si la cadena de entrada contiene caracteres Unicode? ¿Puede ajustar su solución para hacer frente a esta situación?

class Solution {
    public boolean isAnagram(String s, String t) {
       if (s == null || t == null) return false;
        if (s.length() != t.length()) return false;
        if (s.length() == 0 && t.length() == 0) return true;
        char[] chars = s.toCharArray();
        char[] chars1 = t.toCharArray();
        Arrays.sort(chars);
        Arrays.sort(chars1);
        //这里刚开始用的是Arrays.toString转为string然后在eqauls 但是那样执行有 8 -11ms 然后发现这里直接一个循环就搞定了,Arrays.equals也是用的循环比对。
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] != chars1[i]) {
                return false;
            }
        }
        return true;
    }
}

Tiempo de ejecución: 3 ms
Consumo de memoria: 39,8 MB

Otra forma es usar 26 matrices int en el primer carácter único de la cadena. Si las dos cadenas son iguales después de ajustar las posiciones, entonces cada letra debe ser x% 2 == 0. Cada posición de cadena es +1 y otra cadena es -1. Finalmente, cada posición debe ser 0. Entonces, si hay un carácter distinto de cero, uno debe tener más caracteres que el otro.

class Solution {
    public boolean isAnagram(String s, String t) {
       if (s == null || t == null) return false;
        if (s.length() != t.length()) return false;
        if (s.length() == 0 && t.length() == 0) return true;
    
        int[] nums = new int[26];
        
        for(int i = 0;i < s.length();i++) {
            nums[s.charAt(i) - 'a'] ++;
            nums[t.charAt(i) - 'a'] --;
        }
        
        for(int i = 0;i < nums.length;i++) {
            if(nums[i] != 0){
                return false;
            }
        }
        return true;
    }
}
Verificar cuerda palíndromo

Dada una cadena, verifique si es un palíndromo, considere solo letras y números e ignore el caso de las letras.
Explicación: En esta pregunta, definimos una cadena vacía como una cadena palíndromo válida.
Ejemplo 1:
Entrada: "Un hombre, un plan, un canal: Panamá"
Salida: verdadero

Ejemplo 2:
Entrada: "competir con un coche"
Salida: falso

Utilice el método de puntero para comparar.

class Solution {
    public boolean isPalindrome(String s) {
        if(s == null) return false;
        s = s.toLowerCase();
        //之前还加了个计算数字和字母的数量来判断下边循环结束,答案中可以使用i < j来做条件
        int i = 0,j = s.length() - 1;
        while(i < j) {
            char left = s.charAt(i);
            char right = s.charAt(j);
            if(!((left >= 'a' && left <= 'z') ||(left >= '0' && left <= '9') ) ){
                i++;
                continue;
            }

            if(!((right >= 'a' && right <= 'z') ||(right >= '0' && right <= '9'))) {
                j--;
                continue;
            }
            if(left != right) {
                return false;
            }
           
            i++;
            j--;
        }
        return true;
    }
}

Tiempo de ejecución: 3 ms
Consumo de memoria: 39,7 MB

Conversión de cadena a entero (atoi)

Implemente una función atoi para convertir una cadena en un número entero.

Primero, la función descarta los espacios iniciales inútiles según sea necesario, hasta que encuentra el primer carácter sin espacio. Las siguientes reglas de conversión son las siguientes:

Si el primer carácter que no está en blanco es un signo positivo o negativo, combine este signo con tantos caracteres numéricos consecutivos como sea posible después de él para formar un entero con signo.
Si el primer carácter que no está en blanco es un número, se combina directamente con los siguientes caracteres numéricos consecutivos para formar un número entero.
La cadena puede tener caracteres adicionales después de la parte entera válida, por lo que estos caracteres se pueden ignorar y no deberían afectar la función.
Nota: Si el primer carácter que no es un espacio en la cadena no es un carácter entero válido, la cadena está vacía o la cadena contiene solo caracteres en blanco, no es necesario convertir su función, es decir, no se puede convertir de manera efectiva.

En cualquier caso, si la función no puede realizar una conversión válida, devuelva 0.

rápido:

Los caracteres en blanco en esta pregunta solo incluyen el carácter de espacio ''.
Suponiendo que nuestro entorno solo puede almacenar enteros de 32 bits con signo, el rango de valores es [−231, 231 - 1]. Si el valor excede este rango, devuelva INT_MAX (231 - 1) o INT_MIN (−231).

Ejemplo 1:

Entrada: "42"
Salida: 42
Ejemplo 2:

Entrada: "-42"
Salida: -42
Explicación: El primer carácter que no está en blanco es'- ', que es un signo negativo.
Hacemos nuestro mejor esfuerzo para combinar el signo menos con todos los números subsiguientes y finalmente obtenemos -42.
Ejemplo 3:
Entrada: "4193 con palabras"
Salida: 4193
Explicación: La conversión termina en el número '3' porque el siguiente carácter no es un número.

Ejemplo 4:
Entrada: "palabras y 987"
Salida: 0
Explicación: El primer carácter no vacío es 'w', pero no es un número ni un signo positivo o negativo. Por lo tanto, no se puede realizar una conversión efectiva.

Ejemplo 5:
Entrada: "-91283472332"
Salida: -2147483648
Explicación: El número "-91283472332" excede el rango de un entero de 32 bits con signo.
Por lo tanto, se devuelve INT_MIN (−231).

class Solution {
    public int myAtoi(String str) {
        if (str == null || str.length() == 0) return 0;
        boolean haveFirstValidChar = false;
        boolean haveValidNumAfterZero = false;
        boolean isMinus = false;

        int firstCharType = -1; //0 zero 1 symbol 2 validnum

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (!haveFirstValidChar) {
                if (!isValidChar(c)) {
                    return 0;
                } else if (!isSpace(c)) {
                    haveFirstValidChar = true;
                    if (isZero(c)) {
                        firstCharType = 0;
                        if (i == str.length() - 1 || (i < str.length() - 1 && !isNum(str.charAt(i + 1)))) {
                            return 0;
                        }
                    }

                    if (isValidNum(c)) {
                        firstCharType = 2;
                    }

                    if (isValidSymbol(c)) {
                        firstCharType = 1;
                        if (i == str.length() - 1 || (i < str.length() - 1 && !isNum(str.charAt(i + 1)))) {
                            return 0;
                        }
                    }

                    isMinus = (c == '-');

                    if (firstCharType != 0) {
                        sb.append(c);
                    }
                }
            } else if (firstCharType == 0 && isNum(c)) {
                if (haveValidNumAfterZero) {
                    sb.append(c);
                } else if (!isZero(c)) {
                    haveValidNumAfterZero = true;
                    sb.append(c);
                }
            } else if (firstCharType == 1 && isNum(c)) {
                if (haveValidNumAfterZero) {
                    sb.append(c);
                } else if (!isZero(c)) {
                    haveValidNumAfterZero = true;
                    sb.append(c);
                }
            } else if (firstCharType == 2 && isNum(c)) {
                sb.append(c);
            } else {
                break;
            }
        }

        if (!haveFirstValidChar) {
            return 0;
        }

        if ((firstCharType == 0 || firstCharType == 1) && !haveValidNumAfterZero) {
            return 0;
        }

        String result = sb.toString();

        if (result.charAt(0) == '+') {
            result = result.substring(1);
        }

        if (isMinus) {
            if (result.length() < 11) {
                return Integer.valueOf(result);
            } else if (result.length() > 11) {
                return Integer.MIN_VALUE;
            } else {
                int tenInt = Integer.valueOf(result.substring(0, 10));
                int lastInt = Integer.valueOf(result.substring(10, 11));
                return tenInt < Integer.MIN_VALUE / 10 || (tenInt == Integer.MIN_VALUE / 10 && lastInt > 8) ? Integer.MIN_VALUE : Integer.valueOf(result);
            }
        } else if (result.length() < 10) {
            return Integer.valueOf(result);
        } else if (result.length() > 10) {
            return Integer.MAX_VALUE;
        } else {
            int tenInt = Integer.valueOf(result.substring(0, 9));
            int lastInt = Integer.valueOf(result.substring(9, 10));
            return tenInt > Integer.MAX_VALUE / 10 || (tenInt == Integer.MAX_VALUE / 10 && lastInt > 7) ? Integer.MAX_VALUE : Integer.valueOf(result);
        }
    }
    
    private boolean isValidChar(char c){
        return isValidSymbol(c) || isNum(c) || isSpace(c);
    }
    
    private boolean isValidSymbol(char c){
        return '-' == c || '+' == c;
    }
    
    private boolean isNum(char c){
        return c <= '9' && c >= '0';
    }
    
    private boolean isValidNum(char c){
        return c <= '9' && c > '0';
    }
    
    private boolean isSpace(char c){
        return ' ' == c;
    }
    
    private boolean isZero(char c){
        return '0' == c;
    }
}

Tiempo de ejecución: 4 ms
Consumo de memoria: 39,7 MB
Este es mi propio enfoque y el tiempo debe optimizarse. Estudia los algoritmos de otras personas. La brecha surge cuando creo que es demasiado complicado analizarlo y clasificarlo con cuidado.

class Solution {
    public int myAtoi(String str) {
       int res = 0;
        int max = Integer.MAX_VALUE / 10;
        boolean hasStarted = false, isNegative = false;
        for (char ch : str.toCharArray()) {
            if (ch == ' ' && !hasStarted)
                continue;
            else if (ch == '+' && !hasStarted)
                hasStarted = true;
            else if (ch == '-' && !hasStarted) {
                hasStarted = true;
                isNegative = true;
            } else if (ch >= '0' && ch <= '9') {
                hasStarted = true;
                int val = ch - '0';
                if (res > max || (res == max && val > 7))
                    return isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE;
                else
                    res = res * 10 + val;
            } else
                break;
        }

        return isNegative ? -res : res;
    }

}
Implementar strStr ()

Implemente la función strStr ().
Dada una cuerda de pajar y una cuerda de aguja, encuentre la primera posición (comenzando desde 0) donde aparece la cuerda de aguja en la cuerda de pajar. Si no existe, se devuelve -1.

Ejemplo 1:
Entrada: pajar = "hola", aguja = "ll"
Salida: 2

Ejemplo 2:
Entrada: pajar = "aaaaa", aguja = "bba"
Salida: -1

Explicación:
Cuando la aguja es una cuerda vacía, ¿qué valor debemos devolver? Esta es una buena pregunta en una entrevista.
Para esta pregunta, deberíamos devolver 0 cuando la aguja es una cuerda vacía. Esto es consistente con la definición de strstr () en lenguaje C e indexOf () en Java.

class Solution {
    public int strStr(String haystack, String needle) {
        if(haystack == null || needle == null) return -1;
    
       if(haystack.contains(needle)) {
          return haystack.indexOf(needle);
       } else {
           return -1;
       }
        
    }
}

Tiempo de ejecución: 0 ms
Consumo de memoria: 38,3 MB

Esto es relativamente simple y listo para usar, pero le sugiero que mire la implementación de contains e indexOf.

Serie de apariencia

Dado un entero positivo n (1 ≤ n ≤ 30), genera el n-ésimo elemento de la secuencia de aparición.
Nota: Cada elemento de la secuencia entera se representará como una cadena.
"Secuencia de apariencia" es una secuencia de números enteros, comenzando por el número 1, cada elemento de la secuencia es una descripción del elemento anterior. Los primeros cinco elementos son los siguientes:

  1. 1
    
  2. 1 1
    
  3. 2 1
    
  4. 1 2 1 1
    
  5. 1 1 1 2 2 1
    

El primer elemento es el número 1 que
describe el elemento anterior, este número es 1 que es "uno 1", registrado como 11 para
describir el elemento anterior, este número es 11 que es "dos 1", registrado como 21 para
describir el elemento anterior, este número Es 21 que es "uno 2 y uno 1", que se registra como 1211 para
describir el elemento anterior. Este número es 1211, que es "uno 1 uno 2 dos 1", que se registra como 111221

Ejemplo 1:

Entrada: 1
Salida: "1"
Explicación: Este es un ejemplo básico.

Ejemplo 2:
Entrada: 4
Salida: "1211"
Explicación: Cuando n = 3, la secuencia es "21", donde tenemos dos grupos de "2" y "1", "2" se puede pronunciar como "12", que es Frecuencia = 1 y valor = 2; algo como "1" se puede leer como "11". Entonces, la respuesta es "12" y "11" combinados, que es "1211".

class Solution {
    public String countAndSay(int n) {
         if (n < 1 && n > 30) throw new IllegalArgumentException("no serialize");
        if (n == 1) return "1";
        StringBuilder sb = new StringBuilder();

        int count = 1;
        String seed = "1";
        for (int i = 1; i < n; i++) {
            count = 1;
            sb.delete(0,sb.length());
            for (int j = 0; j < seed.length(); j++) {
                if (j + 1 < seed.length()) {
                    if (seed.charAt(j) == seed.charAt(j + 1)) {
                        count++;
                    } else {
                        sb.append(count);
                        sb.append(seed.charAt(j));
                        count = 1;
                    }
                } else {
                    sb.append(count);
                    sb.append(seed.charAt(j));
                }
            }
            seed = sb.toString();
        }

        return sb.toString();
    }
}

Tiempo de ejecución: 4 ms
Consumo de memoria: 37,1 MB

Este es en realidad un bucle de dos capas y el resultado de cada bucle interno es la semilla del siguiente bucle.

Prefijo común más largo

Escriba una función para encontrar el prefijo común más largo en una matriz de cadenas.
Si no hay un prefijo común, se devuelve una cadena vacía "".
Ejemplo 1:
Entrada: ["flor", "flujo", "vuelo"]
Salida: "fl"

Ejemplo 2:
Entrada: ["perro", "coche de carreras", "coche"]
Salida: ""
Explicación: No hay un prefijo común para la entrada.

Nota:
Toda la entrada solo contiene letras minúsculas az.

class Solution {
    public String longestCommonPrefix(String[] strs) {
          if (strs == null || strs.length == 0) return "";

        if(strs.length == 1 && strs[0] != null) return strs[0];
        
        String pre = "";
        boolean havePre = true;
        for (int i = 0; i < strs[0].length(); i++) {
            pre = strs[0].substring(0, i + 1);
            for (int j = 0; j < strs.length; j++) {
                if (!strs[j].startsWith(pre) || strs[j].length() < pre.length()) {
                    if(i == 0) {
                        return "";
                    } else {
                        return pre.substring(0, i);
                    }
                }
            }
        }
        return pre;
    }
}

Tiempo de ejecución: 5 ms
Consumo de memoria: 37,9 MB

Es posible que este método autoescrito no utilice startwith, por lo que puede ser más rápido utilizar caracteres para juzgar.

Eche un vistazo a la forma más rápida:

class Solution {
    public String longestCommonPrefix(String[] strs) {
         if (strs == null || strs.length == 0) {
            return "";
        }
        String pre = strs[0];
        for(String str: strs){
            while(str.indexOf(pre) != 0){
                pre = pre.substring(0,pre.length() - 1);
            }
        }
        return pre;
    }
}

118/118 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 0 ms
Consumo de memoria: 37.8 MB
Esta es una búsqueda de atrás hacia adelante, str.indexOf (pre) == 0 saltar para encontrar el siguiente, si no, acortar el carácter Continúe buscando la cadena y repita la operación anterior.

Supongo que te gusta

Origin blog.csdn.net/u011148116/article/details/107175417
Recomendado
Clasificación