【算法萌新闯力扣】:旋转链表

    力扣题目:旋转链表

开篇

  今天是备战蓝桥杯的第25天和算法村开营第3天!经过这3天的学习,感觉自己对链表的掌握程度大大地提升,尤其是在帮村里的同学讨论相关问题时。本篇文章,给大家带来一道旋转链表的题目,用到了巧妙的快慢指针方法!

题目链接: 61.旋转链表

题目描述


代码思路

 先用双指针策略找到倒数K的位置,也就是{1,2,3}和{4,5}两个序列,之后再将两个链表拼接成{4,5,1,2,3}就行了。具体思路是:
因为k有可能大于链表长度,所以首先获取一下链表长度,如果然后计算应该反转多少次,0次则直接返回原链表。然后
1.快指针先走与反转次数相同的步。
2.慢指针和快指针一起走。
3.快指针走到链表尾部时,慢指针所在位置刚好是要断开的地方。把快指针指向的节点连到原链表头部,慢指针指向的节点断开和下一节点的联系。
4.返回结束时慢指针指向节点的下一节点。

代码纯享版

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || k == 0) return head;
        ListNode fast = head, slow = head;
        int sum = 0;
        ListNode test = head;
        while(test != null){
            sum++;
            test = test.next;
        }
        if(k % sum == 0)return  head;
        int len = k % sum;
        while(len > 0){
            fast = fast.next;
            len--;
        }
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        ListNode newhead = slow.next;
        slow.next = null;
        fast.next = head;

        return newhead;
    }
}

代码逐行解析版

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || k == 0) return head; //排除特殊情况,如果不排除,下面的k%sum中会出现sum==0的报错
        ListNode fast = head, slow = head; //创建快慢指针
        int sum = 0; 
        ListNode test = head; 
        while(test != null){ //利用test来遍历整个链表
            sum++; //sum统计链表的长度
            test = test.next;
        }
        if(k % sum == 0)return  head; //k是sum的整数倍,反转完结果与原链表相同,直接返回原链表
        int len = k % sum; //计算出最终要分开的节点
        while(len > 0){ //先让快指针领先慢指针len个结点
            fast = fast.next; 
            len--;
        }
        while(fast.next != null){ //两个指针同时移动,当快指针到尾结点时,慢指针到达分开的位置
            fast = fast.next;
            slow = slow.next;
        }
        ListNode newhead = slow.next; //三步操作,让慢指针后面的部分拼接到头结点
        slow.next = null;
        fast.next = head;

        return newhead; //此时原本慢指针到下一个结点变成头结点,返回它
    }
}

其他解法

1.第一种是将整个链表反转,如实例1中,把链表变成{5,4,3,2,1},然后再将前K和N-K两个部分分别反转,也就是分别变成了{4,5}和{1,2,3}这样就轻松解决了。

2.力扣官方题解提供了先将链表闭合为环,然后寻找合适的位置断开的解法

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (k == 0 || head == nullptr || head->next == nullptr) {
            return head;
        }
        int n = 1;
        ListNode* iter = head;
        while (iter->next != nullptr) {
            iter = iter->next;
            n++;
        }
        int add = n - k % n;
        if (add == n) {
            return head;
        }
        iter->next = head;
        while (add--) {
            iter = iter->next;
        }
        ListNode* ret = iter->next;
        iter->next = nullptr;
        return ret;
    }
};

结语

  如果这道题的分享对您有所帮助,点个关注,为会每天更新力扣题的分享,与大伙儿一同进步!

你可能感兴趣的:(Java算法,算法,leetcode,链表,java,数据结构)