LeetCode: 3. Algoritmo de doble puntero: puntero de colisión, puntero rápido y lento y su problema de código de lectura

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)

Inserte la descripción de la imagen aquí

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.

Inserte la descripción de la imagen aquí

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

Supongo que te gusta

Origin blog.csdn.net/weixin_46649052/article/details/114419116
Recomendado
Clasificación