Leetcode | Notas sobre el algoritmo del puntero de colisión

La idea básica de los punteros de colisión.

La idea básica de la colisión de punteros es utilizar dos punteros ( o , o, etc.) en estructuras de datos como matrices o listas vinculadas para moverse desde diferentes direcciones (generalmente ambos extremos de la matriz) para buscar , atravesar o juez .leftrightstartend

Los escenarios de uso comunes de los punteros de colisión incluyen:

  1. Búsqueda en matrices ordenadas : los punteros de colisión se pueden utilizar para buscar un elemento de destino en una matriz ordenada. Al apuntar un puntero al principio de la matriz y otro puntero al final de la matriz, según la relación de tamaño entre el elemento señalado por el puntero y el elemento objetivo, el puntero se mueve gradualmente hacia el medio para lograr el propósito de buscando rápidamente el elemento objetivo.

  2. Suma de dos números en una matriz ordenada : dada una matriz ordenada y un número objetivo, puede utilizar el método del puntero de colisión para encontrar dos números en la matriz de modo que su suma sea igual al número objetivo. Al apuntar un puntero al principio de la matriz y el otro al final de la matriz, según la relación entre la suma de los elementos señalados por el puntero y el número objetivo, los punteros se mueven gradualmente para encontrar dos números que cumplir las condiciones.

  3. Juicio de cadena palíndromo : los punteros de colisión se pueden utilizar para juzgar si una cadena es una cadena palíndromo. Al apuntar un puntero al principio de la cadena y el otro al final de la cadena, mueva gradualmente el puntero hacia el centro y compare si los caracteres señalados por los dos punteros son iguales para determinar si la cadena es un palíndromo.

  4. Operaciones de lista vinculada : utilice punteros de colisión para encontrar los nodos intermedios de la lista vinculada, determinar si hay un anillo en la lista vinculada, etc.

  5. ……

La ventaja de un puntero de colisión es que puede completar la tarea en una sola pasada, generalmente con poca complejidad de tiempo y sin requerir espacio adicional .

Sin embargo, el requisito previo para utilizar punteros de colisión es que la estructura de datos de destino debe cumplir ciertas condiciones, como estar ordenada o tener propiedades estructurales específicas.

Ejercicios relacionados con punteros de colisión.

Suma de dos números II: matriz ordenada de entrada

Descripción de la pregunta

Se le proporciona una 1matriz de números enteros cuyos subíndices comienzan desde . La matriz se ha organizado en orden no decreciente. Encuentre dos números numbersde la matriz de modo que la suma de ellos sea igual al número objetivo . targetSi estos dos números son numbers[index1]y respectivamente numbers[index2], entonces 1 <= index1 < index2 <= numbers.length.

Devuelve [index1, index2] la suma subíndice de estos dos números enteros como una matriz de números enteros de longitud 2 .index1 index2

  • Puedes asumir que cada entrada corresponde a una respuesta única y no puedes reutilizar los mismos elementos.

  • La solución que diseñe debe utilizar sólo una cantidad constante de espacio adicional.

Análisis e implementación de problemas.

Estructura de datos: matriz

Método de implementación básico:

  • 对撞指针
Implementación 1: punteros de colisión
# Use Python to solve
def two_sum(numbers, target):
    '''
    查找满足两数之和的位置
    
    参数:
    	numbers(list[int]): 非递减顺序排列的整数数组
    	target(int): 目标数
    返回值:
    	两个整数的下标    	
    '''
    
    # left指针从左往右运动
    # right指针从右往左运动
    left = 0
    right = len(numbers) - 1
    
    while left < right:
        current_sum = numbers[left] + numbers[right]
        # 如果左右指针之和大于目标数,说明right指针需要往左移动一位
        # 反之,left指针需要往右移动一位,通过这样的方式可以有效地缩小搜索空间
        if current_sum > target:
            right -= 1
        elif current_sum < target:
            left += 1
        else:            
   			 return left + 1, right + 1

Análisis de complejidad del tiempo:

  • Complejidad de tiempo promedio: O ( n ) O (n)O ( n ) , donde n es la longitud de la matriz. En el peor de los casos, los punteros izquierdo y derecho se mueven desde ambos extremos de la matriz hacia el centro hasta que se encuentran dos números que cumplen las condiciones o los punteros izquierdo y derecho se encuentran. En promedio, se puede aproximar que los punteros izquierdo y derecho se encuentran en el medio de la matriz, por lo que es necesario atravesar toda la matriz una vez.
  • Mejor complejidad temporal: O ( 1 ) O(1)O ( 1 ) , cuando el valor objetivo no existe en la matriz, la matriz solo necesita atravesarse una vez, es decir, los punteros izquierdo y derecho apuntan al primer y último elemento de la matriz respectivamente, y luego el resultado es Regresó directamente.
  • Peor complejidad de tiempo: O ( n ) O (n)O ( n ) , cuando todos los elementos de la matriz son iguales al valor objetivo, es necesario atravesar toda la matriz, es decir, los punteros izquierdo y derecho se mueven desde ambos extremos hacia el medio hasta que se encuentran.

Análisis de complejidad espacial:

  • O(1) O(1)O ( 1 ) , usando una cantidad constante de espacio extra.

Verificar cadena palíndromo

Descripción de la pregunta

Si después de convertir todos los caracteres en mayúsculas a minúsculas y eliminar todos los caracteres no alfanuméricos, la frase se lee igual al derecho y al revés. Entonces la frase puede considerarse una cadena palíndromo.

  • Las letras y los números son caracteres alfanuméricos.
  • Dada una cadena s, si es un palíndromo, devuelve verdadero; en caso contrario, devuelve falso.

Análisis e implementación de problemas.

Estructura de datos: matriz

Método de implementación básico:

  • puntero de colisión
Implementación 1: punteros de colisión
  1. Primero use la API de cadena en Python:, isalnum()que se usa para verificar si todos los caracteres de la cadena son caracteres alfabéticos y numéricos (es decir, letras o números), y el valor de retorno es un valor booleano.
  2. Luego, use dos punteros: lefty right( izquierda <derecha ) para moverse desde ambos lados hacia el centro para determinar leftsi rightlas sumas son iguales una por una .
  3. Si los valores de ambos lados no son iguales, significa que no es una cadena palíndromo y se devolverá False directamente.
  4. Si son iguales, da un paso leftadelante y rightotro atrás para seguir juzgando hasta que ambos lados lleguen a la mitad de la cuerda.
# Use Python to solve
def is_palindrome(string):
    '''
    检验给定字符串中是否是回文
    参数:
        string (str): 给定字符串
    
    返回值:
        bool
    '''
    
    cleaned_string = "".join(ch.lower() for ch in string if ch.isalnum())
    
    left = 0
    right = len(cleaned_string) - 1
    # 左右指针向字符串中间进发
    while left < right:
        # 如果发现不等,直接返回False
        if cleaned_string[left] != cleaned_string[right]:
            return False
        # 若left和right的值相等,双方继续向中间进发
        left, right = left + 1, right - 1
    # 若遍历完成,说明该字符串是一个回文串
    return True

Análisis de complejidad del tiempo:

  • Complejidad de tiempo promedio: O ( n ) O (n)O ( n ) , donde n es la longitud de la cuerda. En el caso promedio, es necesario recorrer la cadena una vez para construir una nueva cadenacleaned_stringque contenga solo letras y números, convertida a letras minúsculas. Luego,cleaned_stringes necesario atravesar nuevamente la mitad para verificar si se cumple la condición del palíndromo. Por lo tanto, la complejidad del tiempo es lineal, es decir,O ( n ) O (n)O ( n )
  • Mejor complejidad temporal: O ( 1 ) O(1)O ( 1 ) , cuando la cadena es una cadena vacía, el resultado Verdadero se devuelve directamente sin ninguna operación.
  • Peor complejidad de tiempo: O ( n ) O (n)O ( n ) , cuando la cuerda es una cuerda palíndromo, es necesario atravesar la mitad de la cuerda entera, es decir, los punteros izquierdo y derecho se mueven desde ambos extremos hacia el centro.

Análisis de complejidad espacial:

  • O (n) O(n)O ( n ) , crea una nueva cadenacleaned_string que almacena las letras y números de la cadena de entrada, convertidos a minúsculas.

Vocales inversas en cuerda

Descripción de la pregunta

Dada una cadena s, simplemente invierta todas las vocales de la cadena y devuelva la cadena resultante. Las vocales incluyen 'a', 'e', 'i', y pueden aparecer más de una vez tanto en mayúsculas como en minúsculas 'o'.'u'

Análisis e implementación de problemas.

Estructura de datos: matriz

Método de implementación básico:

  • 对撞指针
Implementación 1: punteros de colisión

Podemos usar dos punteros iiyo yjjj atraviesa la cuerda en direcciones opuestas.

  1. Primer indicador iiInicialmente apunto a la cadenassEl primer lugar de s , el punterojj.j inicialmente apunta a la cadenassEl último dígito de s .
  2. En el proceso de recorrido, seguimos cambiando iime muevo hacia la derecha hastaiiseñalo una vocal
  3. Al mismo tiempo seguiamos poniendo jjj se mueve hacia la izquierda hastajjj apunta a una vocal.
  4. En este momento, si i < j i <ji<j , entonces intercambiamosiiyo yjjLa letra vocal señalada por j ; de lo contrario, significa que se han atravesado todas las letras vocales y se puede salir del proceso de recorrido.
# Use Python to solve
def reverse_vowels(s):
    '''
    反转给定字符串中的元音字母
    
    参数:
        s (str): 一个给定字符串
    
    返回值:
        str: 完成反转后的字符串    
    '''
    char_list = list(s)
    length = len(s)
    left = 0
    right = length - 1
    vowel_list = ['a', 'e', 'i', 'o', 'u',
                  'A', 'E', 'I', 'O', 'U']
    while left < right:
        # 在每次循环迭代中,判断 char_list[left](或char_list[right) 是否为元音字母且 left 小于 right,
        # 如果不是,则将 left (或right)指针向右(或左)移动,直到找到一个元音字母。
        while char_list[left] not in vowel_list and left < right:
            left += 1
        while char_list[right] not in vowel_list and left < right:
            right -= 1
        # 找到两个元音字母后,将它们进行反转
        # 然后,将 left 指针向右移动一位,将 right 指针向左移动一位,以继续下一轮迭代。
        char_list[left], char_list[right] = char_list[right], char_list[left]
        left += 1
        right -= 1
    # 最后,使用将字符列表转换为字符串,并将其作为函数的返回值
    return "".join(char_list)

Análisis de complejidad del tiempo:

  • Complejidad de tiempo promedio: O ( n ) O (n)O ( n ) , donde n es la longitud de la cuerda. En el peor de los casos, el puntero izquierdolefty el puntero derechorightse mueven desde ambos extremos de la cadena hacia el centro respectivamente hasta que se encuentren dos vocales que cumplan la condición oleftyrightcumplan. En promedio, se puede aproximar que los punteros izquierdo y derecho se encuentran en el medio de la cadena, por lo que es necesario atravesar toda la cadena una vez.
  • Mejor complejidad temporal: O ( 1 ) O(1)O ( 1 ) , cuando no hay vocales en la cadena, la cadena solo necesita atravesarse una vez, es decir, los punteros izquierdo y derecho están inicialmente en la misma posición y luego el resultado se devuelve directamente.
  • Peor complejidad de tiempo: O ( n ) O (n)O ( n ) , cuando todos los caracteres de la cadena son vocales, es necesario atravesar toda la cadena, es decir, los punteros izquierdo y derecho se mueven desde ambos extremos hacia el medio hasta que se encuentran.

Análisis de complejidad espacial:

  • O (n) O(n)O ( n ) , donde n es la longitud de la cuerda.

El recipiente que contiene más agua.

Descripción de la pregunta

Dada una longitud de nnn altura dela matriz de números enterosaltura . _ _ _ _ _ haynnn líneas verticales,iiLos dos puntos finales de la línea i son (i, 0) (i, 0)( yo ,0 )
( i , altura [ i ] ) ( i, altura [i])( yo ,h e i g h t [ i ])

Encuentre dos de las líneas tales que sean iguales a xxEl eje x juntos forma un recipiente que puede contener la mayor cantidad de agua.

  • Devuelve la cantidad máxima de agua que el contenedor puede almacenar.

Análisis y descripción del tema.

Estructura de datos: matriz

Método de implementación básico:

  • 对撞指针
Implementación 1: punteros de colisión
# Use Python to solve
def max_area(height):
    '''
    解决最大容器问题
    
    参数:
    	height(int): 给定整数数组,表示容器的高度
    	
    返回值:
    	int:最大可容纳水量    
    '''
    # 初始化双指针和最大面积
    left = 0
    right = len(height) - 1
    max_area = 0
	
    # 两个指针向中间移动
    while left < right:
        # 比较两个指针,找到最小的那个
        # 谁小,谁移动
        if height[left] < height[right]:
           max_area = max(max_area, (right - left) * height[left])
           left += 1                
        else:
           max_area = max(max_area, (right - left) * height[right])
           right -= 1
            
    return max_area

Análisis de complejidad del tiempo:

  • Complejidad de tiempo promedio: O ( n ) O (n)O ( n ) , donde n es la longitud de la matriz de alturas de contenedores. En circunstancias promedio, el método del doble puntero se utiliza para atravesar la matriz una vez, determinar la altura mínima del cañón comparando las alturas apuntadas por los punteros izquierdo y derecho, y luego calcular y actualizar el área máxima actual. Por lo tanto, la complejidad del tiempo es lineal, es decir,O ( n ) O (n)O ( n )
  • Mejor complejidad temporal: O ( 1 ) O(1)O ( 1 ) , cuando la matriz de altura del contenedor está vacía o contiene solo un elemento, el resultado 0 se devuelve directamente sin ninguna operación.
  • Peor complejidad de tiempo: O ( n ) O (n)O ( n ) , cuando la matriz de altura del contenedor forma una pendiente grande (aumentando o disminuyendo en altura), es necesario atravesar toda la matriz una vez.

Análisis de complejidad espacial:

  • O(1) O(1)O ( 1 ) , usando una cantidad constante de espacio extra.

Supongo que te gusta

Origin blog.csdn.net/YuvalNoah/article/details/131562895
Recomendado
Clasificación