算法修炼之路——【链表】Leetcode 61旋转链表

题目描述

给定一链表,旋转链表,将链表每个节点向右移动k个位置,其中k是非负数。

示例1:

输入: head = [1, 2, 3, 4, 5], k=2
输出: head = [4, 5, 1, 2, 3]

示例2:

输入: head = [0, 1, 2], k=4
输出: head = [2, 0, 1]

思路分析

直观地理解这道题,即将tail节点一次次的设置为head,设置的次数为k; 这里我们不难发现,会存在链表长度lk的比较关系:

  1. l < k时,需要转移的是链表的一部分;
  2. l = k时,则为原链表;
  3. l > k时,则为几次无用功 + l < k,这时我们需要对lk取余,即l % k

在上述描述过程中,我们其实涉及到两个问题:

  1. 如何以较小代价取得链表长度信息l?或者是如何在获取长度信息的同时做一些有用功?
  2. 当我们得到取余后的k时如何实现需要重新链接的这部分节点?

这里为方便讲解,我们做出图示:

这里我们先考虑两个节点间的互换,可以看图1:
在这里插入图片描述
图 1

如图一所示,我们对原始链表(a)移动了一次节点,得到(b),移动两次得到©,我们不免下意识地会想到 循环链表。因为这里只涉及到了链表headtail的节点变化,我们将图1,以另一种方式来展示会更直观:
在这里插入图片描述
图2

在图2中,我们在原始链表的尾节点5添加了一条辅助指针,且用绿色虚线标注出来。通过图2,我们可以清晰的看到,在链表节点移动的过程中,可以进一步看作是headtail指针指向的节点变化,这样的角度进一步简化了解题的思路。

步骤罗列

  1. 通过遍历找到尾节点oldTail,并使其与当前头节点链接oldTail.next = head,此时会构造出循环链表;
  2. 找到新的尾节点newTail, 且此时新的头节点为其下一节点head = newTail.next
  3. 更新newTail.next = null,返回新的链表头。

解题代码

    public static ListNode solution(ListNode head, int k) {
        if (head == null || k == 0 || head.next == null) {
            return head;
        }

        //init pointers
        ListNode oldTail = head;
        ListNode newTail = head;
        ListNode newHead;
        
        int len; //record the length of list
        
        /* Step 1:
        oldTail move forward to get length of list
        and
        make list to be a circular one
        */
        
        for(len = 1; oldTail.next != null; len++){
            oldTail = oldTail.next;
        }
        oldTail.next = head;
        
       /* Step 2: 
        upgrate newTail and newHead        
        */   
        for(int i = 0; i < (len - k%len -1);i++)
            newTail = newTail.next;
        newHead = newTail.next;
        
        /* Step 3: 
        upgrate newTail.next and return result        
        */
        newTail.next = null;       
        
       return newHead;
    }

复杂度分析

时间复杂度:我们对数据进行了不止一次遍历,但小于两次遍历,故依然为线性级复杂程度,所以时间复杂度为O(N);(这里N与思路分析中的l为同一变量)
空间复杂度:我们没有借助额外的容器,所以空间复杂度为常量级O(1)。

GitHub源码

完整可运行文件请访问GitHub

发布了47 篇原创文章 · 获赞 55 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u011106767/article/details/105322346