31,32 preguntas de LeetCode Top100

31. Siguiente permutación

① Descripción del título
  • Para lograr la función de obtener la siguiente permutación, el algoritmo necesita reorganizar la secuencia dada de números en la siguiente permutación más grande en el orden lexicográfico.
  • Si no hay un arreglo más grande siguiente, reorganice los números al arreglo más pequeño (es decir, en orden ascendente).
  • Debe ser modificado in situ, solo se permite espacio extra constante.
  • A continuación se muestran algunos ejemplos: la entrada está en la columna de la izquierda y la salida correspondiente está en la columna de la derecha.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

② Un recorrido
  • Por ejemplo 158476531, partimos del décimo lugar y no hay más de 3 a la derecha del décimo lugar. Mirando las centenas, no hay más de 5 a la derecha de las centenas. Hasta 4, hay muchos más de 4 a la derecha, elija el que sea un poco mayor que 4, es decir, 5. Luego, intercambie, se convierte en 158 576 431. El número se vuelve más grande, pero no solo es mayor 158476531. También necesitamos ordenar los números en el lado derecho de 5 de pequeño a grande. Se convierte en 1585 13467y puede acabarse.
  • Para el proceso de análisis específico, consulte la animación .
  • el código se muestra a continuación:
public void nextPermutation(int[] nums) {
    
    
    int i = nums.length - 2; // 从十位开始找
    //找到第一个不再递增的位置
    while (i >= 0 && nums[i + 1] <= nums[i]) {
    
    
        i--;
    }
    //如果到了最左边,就直接倒置输出
    if (i < 0) {
    
    
        reverse(nums, 0);
        return;
    }
    int j = nums.length - 1;
    //找到刚好大于 nums[i]的位置
    while (nums[j] <= nums[i]) {
    
    
        j--;
    }
    // 交换数字
    swap(nums, i, j);
    //对目标位置的右侧进行倒置
    reverse(nums, i + 1);
}

public void reverse(int[] nums, int start) {
    
    
    int end = nums.length - 1;
    while (start < end) {
    
    
        swap(nums, start, end);
        start++;
        end--;
    }
}

public void swap(int[] nums, int i, int j) {
    
    
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

32. Paréntesis válido más largo

① Descripción del título
  • Teniendo en cuenta que sólo contiene '('y ')'cuerdas, para encontrar la más larga sub-cadena comprende un paréntesis eficaces.
  • Ejemplo 1:

Entrada: "(()"
Salida: 2
Explicación: La subcadena de corchetes válida más larga es "()"

  • Ejemplo 2:

Entrada: “) () ())”
Salida: 4
Explicación: La subcadena de corchete válida más larga es “() ()”

② Ley de Violencia ( Time Limit Exceeded)
  • La longitud de la subcadena que contiene el paréntesis de prioridad debe ser un número par, por lo que solo las subcadenas con la longitud de 2, 4, 6, ... deben juzgarse.
  • Para juzgar la subcadena con longitud 2, comience desde el subíndice 0, y solo hay un tipo de subcadena para cada subíndice (i,i+1)y , al mismo tiempo, la subcadena del último grupo de subcadenas debería ser i <= len - curLen.
  • El método de uso del auxiliar isValiddetermina si la subcadena actual contiene paréntesis válidos, si es truey max < curLenpuede actualizarse como máx. Nota: En este momento curLen += 2, se puede juzgar la subcadena de longitud , porque solo estamos obligados a encontrar la longitud, no todas las subcadenas.
  • Error de ejecución: el Time Limit Exceededcódigo es el siguiente:
public int longestValidParentheses(String s) {
    
    
    int len = s.length();
    if (len == 0) {
    
    
        return 0;
    }

    int max = 0;
    for (int curLen = 2; curLen <= len; curLen += 2) {
    
    
        for (int i = 0; i <= len - curLen; i++) {
    
    
            int start = i;
            int end = start + curLen - 1;
            if (isValid(s, start, end) && max < curLen) {
    
    
                max = curLen;
                break;
            }
        }
    }
    return max;
}

public boolean isValid(String s, int start, int end) {
    
    
    int count = 0;
    for (int i = start; i <= end; i++) {
    
    
        if (s.charAt(i) == '(') {
    
    
            count++;
        } else {
    
    
            count--;
        }
        if (count < 0) {
    
    
            return false;
        }
    }
    return count == 0;
}
③ Optimización de la ley de violencia
  • En la solución uno, haremos muchos juicios repetidos. Por ejemplo, como este, () () (), comenzando desde el subíndice 0, primero juzgamos si la longitud 2 es una secuencia legal. Luego juzgue si la cadena de longitud 4 coincide, pero comenzará desde el subíndice 0. Al juzgar una cadena con una longitud de 6, todavía comienza desde 0, pero de hecho, se ha confirmado que los primeros 4 han formado una secuencia legal, por lo que podemos empezar desde el subíndice 4 para juzgar.
  • Basándonos en esto, podemos cambiar nuestra forma de pensar, podemos juzgar cuánto tiempo es la subcadena legal más larga de cada posición. Para determinar si es una subcadena legal, no usamos la pila, pero usamos una variable para registrar la situación actual del paréntesis. Al encontrar el corchete izquierdo, agregue 1 y encuentre el corchete derecho menos 1. Si se convierte en 0, actualizamos la subcadena legal más larga cuerda.
  • Nota: El ciclo externo icomienza desde 0 y la condición de ejecución es i < len; el ciclo interno jcomienza desde la j = icondición de ejecución j < len. i < lenLa suma j = ies para asegurar que no es necesario actualizar el recuento antes del ciclo interno .
  • O(n²)Complejidad del tiempo :.
  • O(1)Complejidad espacial :.
  • el código se muestra a continuación:
public int longestValidParentheses(String s) {
    
    
    int len = s.length();
    if (len == 0) {
    
    
        return 0;
    }
    int max = 0;
    for (int i = 0; i < len; i++) {
    
    
        int count = 0;
        for (int j = i; j < len; j++) {
    
    
            if (s.charAt(j) == '(') {
    
    
                count++;
            } else {
    
    
                count--;
            }
            if (count == 0 && max < (j - i + 1)) {
    
    
                max = j - i + 1;
                continue;
            }
            if (count < 0) {
    
    
                break;
            }
        }
    }
    return max;
}
④ Programación dinámica
  • Úselo para dp[i]indicar el paréntesis válido más largo cuyo subíndice termina con i.
  • Cuando s[i]='('el tiempo, dp[i]=0sin actualizar dp[i]el valor de permitido efectivo como valor inicial 0. paréntesis imposible porque la composición;
  • Cuando llegue s[i]=')'el momento, hay dos casos:
    s[i-1]='('cuando dp[i] = dp[i - 2] + 2;
    s[i-1]=')'y s[i - dp[i - 1] - 1]== '('cuandodp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2 .
  • Nota:
    i = 1Empiece directamente desde el subíndice , ya que i = 0, no pueden existir paréntesis válidos independientemente del valor.
    ② Cuando s[i-1]='(', actualice dp[i] = dp[i - 2] + 2, asegúrese de juzgar i - 2 >= 0. Debido a que puede ser ()o (()o )()situación.
    ③ Cuando s[i-1]=')'quiera juzgar, s[i - dp[i - 1] - 1]== '('primero debe juzgar i - dp[i - 1] - 1 >= 0. Porque puede ser ())el caso.
    ④ Cuándo s[i-1]=')'y s[i - dp[i - 1] - 1]== '('cuándo actualizar dp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2, asegúrese de juzgar i - dp[i - 1] - 2 >= 0). Porque puede ser (())el caso.
  • el código se muestra a continuación:
public int longestValidParentheses(String s) {
    
    
    int len = s.length();
    if (len == 0) {
    
    
        return 0;
    }
    int max = 0;
    int[] dp = new int[len];
    for (int i = 1; i < len; i++) {
    
    
        if (s.charAt(i) == ')') {
    
    
            if (s.charAt(i - 1) == '(') {
    
    
                dp[i] = (i - 2 >= 0) ? dp[i - 2] + 2 : 2;
            } else {
    
    
                if (i - dp[i - 1] - 1 >= 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
    
    
                    dp[i] = (i - dp[i - 1] - 2 >= 0) ? dp[i - dp[i - 1] - 2] + dp[i - 1] + 2 : dp[i - 1] + 2;
                }
            }
            max = Math.max(dp[i], max);
        }
    }
    return max;
}

Supongo que te gusta

Origin blog.csdn.net/u014454538/article/details/90474970
Recomendado
Clasificación