Algoritmo: la idea de resolver el problema del doble puntero

Algoritmo de punteros duales, a veces te sientes muy listo, resuelves muchos problemas, es necesario resumir, en primer lugar el de dos punteros es un concepto muy amplio, que es un recorrido similar i 和 jpero la diferencia es que los dos punteros se mueve en el Al mismo tiempo, es decir, no aporta la complejidad de O(N)a a O(N*N), por lo que es elogiado por muchos líderes de algoritmos, por lo que con base en esta inducción, resumimos las soluciones y rutinas comunes de punteros duales.

1. Introducción al tipo de pregunta

Hay tres tipos de preguntas, que son las siguientes:

  • Punteros rápidos y lentos (presione los dos punteros que no están sincronizados antes y después)

  • Punteros dobles delanteros y traseros (uno en la cabeza, uno en la cola, acercándose al centro)

  • Punteros de intervalo fijo (dos punteros con un espaciado de i, i + k)

Como se mencionó anteriormente, estos tres punteros se pueden completar atravesando la matriz una vez, y su complejidad de tiempo es menor o igual a O(N), y la complejidad de espacio se O(1)debe a que solo se almacenan dos punteros.

2. Tipos de preguntas habituales

2.1 Punteros rápidos y lentos

Una pregunta bastante clásica:

  • Determine si la lista vinculada tiene un anillo

A través de los dos punteros a diferentes ritmos, muévase uno tras otro hasta que los punteros coincidan

https://leetcode.com/problems/linked-list-cycle/description , el fragmento de código es el siguiente:

public boolean hasCycle(ListNode head) {
    ListNode slow = head;
          ListNode fast = head;
    while (slow != null && fast != null) {
                 ListNode n = fast.next;
     fast = n == null ? null : n.next;
     if (slow == fast) {
         return true;
     }
                 slow = slow.next;
    }
    return false;
    }

El código se resuelve de la siguiente manera:

public int findDuplicate(int[] nums) {
        // 将其看成是一个循环的链表,快慢指针循环
        int index1 = 0;
        int index2 = 0;
        do
        {
            index1 = nums[index1];
            index2 = nums[index2];
            index2 = nums[index2];

        }while (nums[index1] != nums[index2]);
        index1 = 0;
// 找出在哪个位置为起始点,可证必定在圆圈起点相遇
        while(index1 != index2){
            index1 = nums[index1];
            index2 = nums[index2];
        }
        return index1;
    }

2.2 Punteros de punto final delantero y trasero

  • Búsqueda binaria

La búsqueda binaria es un tipo de pregunta típico con punteros delanteros y traseros. El código es el siguiente:

public static int binarySearch(int[] array, int targetElement) {
    int leftIndex = 0, rightIndex = array.length - 1, middleIndex = (leftIndex + rightIndex) / 2;

    while(leftIndex <= rightIndex) {
      int middleElement = array[middleIndex];
      if(targetElement < middleElement) {
        rightIndex = middleIndex - 1;
      }else if(targetElement > middleElement) {
        leftIndex = middleIndex + 1;
      }else {
        return middleIndex;
      }

      middleIndex = (leftIndex + rightIndex) / 2;
    }

    return -1;
  }

2.3 Punteros a intervalos fijos

// 快指针q每次走2步,慢指针p每次走1步,当q走到末尾时p正好走到中间。

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode p = head, q = head;
        while (q != null && q.next != null) {
            q = q.next.next;
            p = p.next;
        }
        return p;
    }
}
    // 快慢指针,先让快指针走k步,然后两个指针同步走,当快指针走到头时,慢指针就是链表倒数第k个节点。

    public ListNode getKthFromEnd(ListNode head, int k) {

        ListNode frontNode = head, behindNode = head;
        while (frontNode != null && k > 0) {

            frontNode = frontNode.next;
            k--;
        }

        while (frontNode != null) {

            frontNode = frontNode.next;
            behindNode = behindNode.next;
        }

        return behindNode;
    }

3. Resumen de la plantilla

Después de leer los tres códigos, ¿crees que es muy simple? Aquí tienes un resumen de las tres plantillas de código de doble puntero

// 1.快慢指针
l = 0
r = 0
while 没有遍历完
  if 一定条件
    l += 1
  r += 1
return 合适的值

//2. 左右端点指针
l = 0
r = n - 1
while l < r
  if 找到了
    return 找到的值
  if 一定条件1
    l += 1
  else if  一定条件2
    r -= 1
return 没找到

//3. 固定间距指针
l = 0
r = k
while 没有遍历完
  自定义逻辑
  l += 1
  r += 1
return 合适的值

Wu Xie, Xiao San Ye, un pequeño novato en segundo plano, big data e inteligencia artificial. Presta atención a másarchivo

Supongo que te gusta

Origin blog.csdn.net/hu_lichao/article/details/110358651
Recomendado
Clasificación