- Grabado el 23 de mayo de 2019
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 1585
764
31. El número se vuelve más grande, pero no solo es mayor158476531
. También necesitamos ordenar los números en el lado derecho de 5 de pequeño a grande. Se convierte en 158513467
y 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 seri <= len - curLen
. - El método de uso del auxiliar
isValid
determina si la subcadena actual contiene paréntesis válidos, si estrue
ymax < curLen
puede actualizarse como máx. Nota: En este momentocurLen += 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 Exceeded
có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
i
comienza desde 0 y la condición de ejecución esi < len
; el ciclo internoj
comienza desde laj = i
condición de ejecuciónj < len
.i < len
La sumaj = i
es 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]=0
sin actualizardp[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]='('
cuandodp[i] = dp[i - 2] + 2
;
②s[i-1]=')'
ys[i - dp[i - 1] - 1]== '('
cuandodp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2
. - Nota:
①i = 1
Empiece directamente desde el subíndice , ya que i = 0, no pueden existir paréntesis válidos independientemente del valor.
② Cuandos[i-1]='('
, actualicedp[i] = dp[i - 2] + 2
, asegúrese de juzgari - 2 >= 0
. Debido a que puede ser()
o(()
o)()
situación.
③ Cuandos[i-1]=')'
quiera juzgar,s[i - dp[i - 1] - 1]== '('
primero debe juzgari - dp[i - 1] - 1 >= 0
. Porque puede ser())
el caso.
④ Cuándos[i-1]=')'
ys[i - dp[i - 1] - 1]== '('
cuándo actualizardp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2
, asegúrese de juzgari - 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;
}