[路飞]_leetcode刷题_61. 旋转链表

187 阅读2分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

题目_旋转链表

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

 

示例 1:

暴力解法

拿到这题,第一反应就是,找到链表倒数第二个节点,然后将倒数第二个节点的指针指向null,将最后一个节点的指针指向头节点,循环k次即可。
再考虑边界情况,空链表,或者链表只有一个节点,则直接返回头节点。

三下五除二,解法写出来了,但是,时间超限制了,哈哈。

没事,分析发现,假设链表长度是4

旋转次数为4,那么实际旋转0次

旋转次数为5,那么实际旋转1次

旋转次数为k, 那么实际旋转次数为(k/链表长度)得到的余数,即k%length

暴力解法代码

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    if(!head || !head.next || k == 0){
        return head
    }
    let length = getListLength(head)
    let realCount = k%length
    let headNode = head
    for(let i=0;i<realCount;i++){
        let lastSecondNode = getLastSecondNode(headNode)
        let lastNode = lastSecondNode.next
        lastSecondNode.next = null
        lastNode.next = headNode
        headNode = lastNode
    }

    return headNode
};

function getListLength(head){
    let cur = head
    let length = 0
    while(cur){
        cur = cur.next
        length++
    }
    return length
}

function getLastSecondNode(head){
    let cur = head
    while(cur && cur.next && cur.next.next){
        cur = cur.next
    }
    return cur
}

链表成环再截断解法

假设链表长度是4,循环5次,其实可以理解为,头节点向右移动3次

那么~~

假设链表长度是L,循环K次,其实可以理解为,头节点向右移动L - K/L

那么我们可以

1.拿到链表长度length
2.将链表成环
3.计算移动步数move
4.从头节点开始向右移动move步,找到真正的头节点
5.截断链表,返回真正的头节点

链表成环解法代码如下

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    // 链表节点为0或1 || 循环次数为0
    if(!head || !head.next || k == 0){
        return head
    }
    // 获取链表长度
    let cur = head
    let length = 1
    while(cur.next){
        cur = cur.next
        length++
    }
    cur.next = head  //链表成环
    let move = length - k%length  //计算移动步数
    let realHead = head  //realHead用于存放真正的头节点,return的就是这个realhead
    let lastHead  //lastHead用于存放真正的尾节点,用来截断链表
    while(move){
        lastHead = realHead
        realHead = realHead.next
        move--
    }
    lastHead.next = null
    return realHead
};