算法_旋转链表(#61)

131 阅读2分钟

题目

给一个链表头节点,旋转链表,将链表每个节点向右边移动k个位置。

image.png

分析一波

k:代表向右移动的位数;
n: 指的是链表的长度,链表有几位节点;
因为题目并没有告诉k和n的关系,也就是说没说k会比n小,所以,k的数字可能会很大;
因此,为了不必要的多余操作转多余的圈,我们用对k取余的方式; 对k取余。多余的圈数去掉; k是从后往前找;

思路

先把链表最后一个节点和头节点head连接起来,
围成一个圈,然后找到k (是从后面数是k,从前面数就是n-k+1,n是链表的总节数,k是题目中的向右移动几位)的位置,
分开,也就是从头数到第n-k+1的位置断开,也就是它的后面的节点设置为null,
把之前后面的节点指向头节点就ok啦

将链表形成一个圈,
找到K的位置,
然后将它下一个节点设置为null,
再将原先的下一个节点指向head,
就是断开k之前的,之后的设置为头节点。

实践,上代码

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    if(!head) return head;
    let p=head,n=1;
    while(p.next){
      p=p.next;
      n++;
    }
    //这里就算是把链表围成一个圈了。
    p.next=head;
    k%=n,k=n-k;
   while(k--) p=p.next;
   head=p.next;
   p.next=null;
   return head;
};

专门设置个n来计算链表的长度,这点很重要。
开始是把链表围成一个圈了。
最后的k是(也就是第二个运算中的k,第一个运算的k还是正着数的k的位置)计算正着数k的位置,这里比较巧妙使用对k%n去余,去掉多余的圈数,因为并没有告诉k个链表长度之间的关系,有可能k非常大,然后又比如k=3n+1.这里计算后面的1就用取余。 p.next设置为头,是head=p.next而不是p.next=head; 返回的是head不是p
就是先计算出链表的长度然后围成一个圈,然后计算出链表正着数k的位置,断掉k后面的节点,然后把k位置之前后面节点改为头部节点。