Directorio de artículos
Introducción
La aritmética de doble puntero se usa con mucha frecuencia en problemas de arreglos. Los punteros dobles se utilizan principalmente para recorrer la matriz, y los dos punteros apuntan a diferentes elementos para completar la tarea juntos.
1. Puntero de colisión
El método del puntero de colisión, como sugiere el nombre, consiste en que el puntero choca en el medio en ambos lados. Ver tres
En segundo lugar, el puntero de velocidad
El indicador de velocidad puede entenderse como: un corredor rápido y un corredor lento corren en una pista circular, en un momento determinado, el corredor rápido alcanzará al corredor lento por detrás. El puntero rápido se mueve rápidamente dos pasos a la vez, y el puntero lento se mueve un paso a la vez, y eventualmente se encontrará en una cierta posición en el anillo (mínimo común múltiplo)
Hay dos situaciones:
1 rápido va al final de la lista vinculada y devuelve nulo
2 rápido = lento, los dos punteros se encuentran por primera vez, el puntero bajo s comienza desde la posición de reunión y la posición de inicio al mismo tiempo, y la posición de reunión es la entrada del anillo (puedes recordar si no entiendes)
Prueba:
a = el número de pasos desde el principio hasta la entrada del anillo = 4
b = el número de pasos en un anillo = 5
rápido = 2 * lento = 2
lento = 1 Al
reunirse, el número de pasos rápidos = el número de pasos lentos + el número de pasos en el anillo n; El número de pasos dados por rápido es igual al doble del número de pasos dados por lento. Por lo tanto, el número de pasos dados en
lento es el mismo que el número de pasos en el bucle rápido = lento + nb => lento = nb
Tres, LeetCode — 167
Dada una matriz de números enteros ordenados y un objetivo de números enteros, busque dos elementos en él y haga la suma del objetivo. Devuelve los índices de estos dos números.
Ejemplo: nums = [2,7,11,15], target = 9
Resultado: [1,2]
- ¿Y si no hay solución? Solución garantizada
- ¿Y si hay varias soluciones? Devuelve cualquier solución
Nota:
¿Es 3,3 + 3 + 3 = 9 en números?
Problema de índice, ya sea para comenzar desde 1 o desde 0
Solución 1:
Solución violenta, doble recorrido, el grado de tiempo es O (n ^ 2), ¡ fácil de detener ! ! !
class Solution:
def findTwosum(self, num, target):
"""
在有序数组中,找到两数和为标签
:param num:
:param target:
:return:
"""
return self.violentSolution(num, target)
def violentSolution(self, num, target):
length = len(num)
# 双循环
for i in range(length):
for j in range(length):
if num[i] + num[j] == target:
return [i, j]
def main():
num = [2, 3, 5, 7, 9, 10]
target = 9
s = Solution()
solution = s.findTwosum(num, target)
print('返回索引为', solution)
if __name__ == '__main__':
main()
Solución 2: La
solución de fuerza bruta no hace un uso completo de la naturaleza de la matriz original (ordenada), por lo que deberíamos pensar en usar la búsqueda binaria, y su complejidad de tiempo es O (nlogn).
La búsqueda binaria también se llama media búsqueda. La ventaja es que el número de comparaciones es pequeño, la velocidad de búsqueda es rápida y el rendimiento promedio es bueno; la desventaja es que la tabla a buscar debe ser una lista ordenada, y es difícil de insertar y eliminar. Por lo tanto, el método de búsqueda binaria es adecuado para buscar listas ordenadas con frecuencia que no cambian con frecuencia.
El principio de búsqueda binaria: Primero, suponga que los elementos de la tabla están ordenados en orden ascendente. Compare las palabras clave registradas en la posición media de la tabla con las palabras clave de búsqueda. Si las dos son iguales, la búsqueda es exitosa; de lo contrario, use los registros de la posición media para dividir la tabla en frente y reverso Para las dos subtablas, si la clave registrada en la posición intermedia es mayor que la clave de búsqueda, se busca más en la subtabla anterior, de lo contrario se busca en la última subtabla más buscado. Repita el proceso anterior hasta que se encuentre un registro que cumpla con las condiciones y la búsqueda sea exitosa, o hasta que la subtabla no exista, la búsqueda no sea exitosa en este momento.
class Solution:
def findTwosum(self,numbers,target):
"""
二分查找
:param num: 数组
:param target: 值
:return: 返回索引
"""
return self.binary_search(numbers,target)
def binary_search(self,numbers,target):
n = len(numbers)
for i in range(n):
low, high = i + 1, n - 1
while low <= high:
mid = (low + high) // 2
if numbers[mid] == target - numbers[i]:
return [i + 1, mid + 1]
elif numbers[mid] > target - numbers[i]:
high = mid - 1
else:
low = mid + 1
def main():
num = [2, 7, 11, 15]
target = 9
s = Solution()
solution = s.findTwosum(num, target)
print('索引为', solution)
if __name__ == '__main__':
main()
Solución 3: El
método del puntero de colisión, como sugiere el nombre, es que el puntero golpea el centro en ambos lados. Complejidad espacial O (1)
class Solution:
def findTwosum(self, num, target):
return self.collision_pointer(num, target)
def collision_pointer(self, num, target):
"""
对撞指针
:param num: 有序数组
:param target: 标签
:return: 返回索引
"""
i, j = 0, len(num) - 1
while i < j:
if num[i] + num[j] == target:
break
elif num[i] + num[j] > target:
j -= 1
else:
i += 1
if num[i] + num[j] == target:
return [i + 1, j + 1]
else:
print('List is not solution!!!')
def main():
num = [2, 7, 11, 15]
target = 9
s = Solution()
solution = s.findTwosum(num, target)
print('索引为', solution)
if __name__ == '__main__':
main()
Otros problemas al usar punteros que colisionan
125. Determinar si es una cuerda palíndromo
Dada una cadena, solo mire los números y letras en ella, ignorando el caso, y juzgue si la cadena es una cadena palíndromo
class Solution:
def isPalindrome(self, s):
return self.pointer(s)
# 对撞指针解回文字符串
def pointer(self, s):
s = s.lower()
# 去掉除字符串与数字外的其他
s = [i for i in s if i.isalpha() or i.isnumeric()]
s = "".join(s)
i, j = 0, len(s) - 1
while i < j:
if s[i] == s[j]:
i += 1
j -= 1
else:
return False
return True
def main():
s = "A man, a plan, a canal: Panama"
ss = Solution()
solution = ss.isPalindrome(s)
print(solution)
if __name__ == '__main__':
main()
344. Cuerda invertida
Dada una cadena, devuelve la cadena invertida de esta cadena
class Solution:
def reverseString(self, s) :
return self.pointer(s)
def pointer(self,s):
i,j = 0,len(s)-1
while i < j:
s[i],s[j] = s[j],s[i]
i += 1
j -= 1
return s
def main():
s = ["h","e","l","l","o"]
ss = Solution()
solution = ss.reverseString(s)
print(solution)
if __name__ == '__main__':
main()
345. Voltea las vocales en la cuerda
Dada una cuerda, voltea las vocales en la cuerda
# 元音字母有'a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U'
class Solution:
def reverseVowels(self, s):
return self.pointer(s)
def pointer(self, s):
s = [i for i in s]
# print(s)
i, j = 0, len(s) - 1
while i < j:
if s[i] not in ['a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U']:
i += 1
elif s[j] not in ['a', 'e', 'i', 'o', 'u','A', 'E', 'I', 'O', 'U']:
j -= 1
else:
s[i], s[j] = s[j], s[i]
i += 1
j -= 1
s = ''.join(s)
return s
def main():
s = "hello"
ss = Solution()
solution = ss.reverseVowels(s)
print(solution)
if __name__ == '__main__':
main()
Cuatro, LeetCode — 142
142. Lista circular vinculada II
Dada una lista vinculada, devuelve el primer nodo en el anillo de la lista vinculada. Si la lista vinculada no tiene anillos, se devuelve un valor nulo. Para representar los anillos en una lista vinculada dada, usamos el entero pos para indicar la posición donde el final de la lista vinculada está conectado a la lista vinculada (el índice comienza desde 0). Si pos es -1, significa que no hay ningún anillo en la lista vinculada. pos solo se usa para identificar el caso del anillo y no se pasará a la función como parámetro.
Nota: No está permitido modificar la lista vinculada dada.
Entrada: head = [3,2,0, -4], pos = 1
Salida: Devuelve el nodo de la lista enlazada con el índice 1
Explicación: Hay un anillo en la lista enlazada, y su cola está conectada al segundo nodo
Si usamos un Conjunto para guardar los nodos visitados, podemos recorrer toda la lista vinculada y devolver el primer nodo duplicado. La complejidad del espacio es O (n)
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
record = set()
while head:
if head in record:
return head
record.add(head)
head = head.next
return None
Condición agregada: la complejidad del espacio es O (1)
Conocimiento de la lista vinculada
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast,slow = head,head
while fast != None:
fast = fast.next
if fast == None:
break
fast = fast.next
slow = slow.next
if slow == fast:
break
# 链表中没有环
if fast == None:
return None
p1,p2 = slow,head
while p1 != p2:
p1 = p1.next
p2 = p2.next
return p1