61. rotación Lista **

61. rotación Lista **

https://leetcode.com/problems/rotate-list/

título Descripción

Dada una lista enlazada, gire la lista a la derecha por k lugares, donde k es no negativo.

Ejemplo 1:

Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL

Ejemplo 2:

Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL

Implementación en C ++ 1

Me presenté por primera vez las ideas más recientes de la misma, y ​​luego mirar la práctica anterior.

El código siguiente es la idea:

  1. En primer lugar voltear toda la lista
  2. Antes de invertir knodo, y luego la vuelta los num - knodos
  3. El empalme de dos sub-listas

Como la idea general, pero hay algunos detalles a tener en cuenta, a su vez, introducir la siguiente:

  1. En primer lugar, kno puede ser muy grande, si conocemos el número de nodos de la lista num, sólo tenemos que hacer frente a k %= numla situación. Con el fin de contar el número de nodos de lista enlazada, esto se hace en la cara de esta lista, por lo que reverseel aumento de la función int &numde este parámetro.
  2. Tan sólo hay que tener en cuenta k %= numla situación, y si en este momento k == 0, y luego volver directamente a la lista original, pero la lista en el primer paso ha sido volteado, por lo que prestar atención a voltear hacia atrás.
  3. Después de introducir los dos primeros pasos, originalmente destinado a revocar hace knodos, entonces volteadas hacia atrás de num - knodos, pero se encuentra que hay un problema que no es efectivamente empalme dos listas, si desea empalmar dos listas, es necesario encontrar la última antes de un nodo secundario de la lista, por supuesto, también es posible hacerlo, pero no se sienten muy elegante.
  4. Por lo tanto, otra manera es para voltear primero la parte posterior de num - klos nodos después de la finalización de efecto de vuelco es como sigue:
  1. Después de que el tercer paso, es necesario dar la vuelta 5->4, y dejar que el 5punto 1. De hecho, esta idea y reversefunción de la lógica es la misma.
    Pero hay una necesidad de prestar atención a los detalles, headla mayoría se mueve a 4, lo que equivale a 3un extremo de la cabeza, tenemos que utilizar end = p->nextprimero 3guardado en endla , pero no se puede whileutilizar directamente en el ciclo head != p->next; es porque el nodo 4último cambio, la p correspondiente va a cambiar, lo que lleva a la final p->nextque ningún punto 3 ya continuación con una descripción breve de la figura paso:
class Solution {
private:
    ListNode* reverse(ListNode *head, int &num) {
        ListNode *prev = nullptr;
        while (head) {
            auto tmp = head->next;
            head->next = prev;
            prev = head;
            head = tmp;
            num += 1;
        }
        return prev;
    }
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (!head || !head->next) return head;
        int num = 0;
      	// 第一步
        head = reverse(head, num);
        k = k % num;
        if (k == 0) return reverse(head, num);
        auto p = head;
        while (--k) p = p->next;
        // 第二步
        auto rlist = p->next;
        rlist = reverse(rlist, num);
        // 第三步
        auto end = p->next;
        while (head != end) {
            auto tmp = head->next;
            head->next = rlist;
            rlist = head;
            head = tmp;
        }
        return rlist;
    }
};

2 en C ++

Hace dos años, el código:

Idea: usar recursividad puede ser una solución muy simple Esta pregunta, si desea una lista de los tiempos de rotación k, que se puede girar en k - 1 sobre la base de la lista del último nodo en la cabecera de la lista, a fin de obtener la k veces la lista. pero hay optimización es importante tener en cuenta, de lo contrario, informar de un tiempo de espera, después de todo, puede ser grande k, se observa que, si k es divisible por el número de nodos de la lista, a continuación, la lista estará lista original girado en sí.

class Solution {
private:
    ListNode* rotateRight(ListNode *head, int n, int k) {
      	// 如果 k 能整除 n, 那么直接返回链表本身
        if ((k % n) == 0) return head;
		
      	// 否则只要在第 k-1 次旋转得到的链表的基础上, 做一些简单的操作即可.
      	// 注意 while 循环中判断 ptr->next->next 是否存在, 这样是为了让
      	// ptr 最终的值是倒数第二个节点.
        head = rotateRight(head, n, k - 1);
        auto ptr = head;
        while (ptr->next && ptr->next->next)
            ptr = ptr->next;
        auto tmp = ptr->next;
        ptr->next = nullptr;
        tmp->next = head;
        head = tmp;
        return head;

    }
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (!head || !head->next) return head;
      	// 用 n 统计链表中节点的个数
        int n = 0;
        auto ptr = head;
        while (ptr) {
            ptr = ptr->next;
            ++ n;
        }
        return rotateRight(head, n, k);
    }
};

C ++ aplicación 3

De LeetCode Foro:

Mi limpia código C ++, bastante estándar (Encontrar cola y vuelva a conectar la lista)

Idea de este enfoque es determinar primero el tamaño de la lista y encontrar el último nodo de cola, entonces infligido cadena cíclica tail->next = head. Según Después de k %= lendeterminar dónde lista desconexión. (Si no se utiliza una sentencia if k %= len, el bucle for la condición de determinación i < len - kes en realidad i < len - k % len.

. Corresponde al primer anillo, entonces dejaron tailPara mover len - kpaso intuitivo pensar que, si el puntero se puede mover hacia atrás, el retroceso kpaso es más conveniente; si no puede moverse hacia atrás, entonces podemos avanzar len - kpaso.

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head) return head;
        
        int len=1; // number of nodes
        ListNode *newH, *tail;
        newH=tail=head;
        
        while(tail->next)  // get the number of nodes in the list
        {
            tail = tail->next;
            len++;
        }
        tail->next = head; // circle the link

        if(k %= len) 
        {
            for(auto i=0; i<len-k; i++) tail = tail->next; // the tail node is the (len-k)-th node (1st node is head)
        }
        newH = tail->next; 
        tail->next = NULL;
        return newH;
    }
};
Publicados 455 artículos originales · ganado elogios 8 · Vistas a 20000 +

Supongo que te gusta

Origin blog.csdn.net/Eric_1993/article/details/105004378
Recomendado
Clasificación