链表每个节点向右循环移动 k 个位置(LeetCode--61.旋转链表)

题目描述

将一个链表每个节点向右循环移动 k 个位置。

示例:
输入:1->2->3->4->5->NULL, k = 2
输出:4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

解析

实现技巧

仔细观察循环右移结果,可以发现规律,一个包含n个元素的链表每个结点循环移动k个位置实际上就是链表中的后k(k = k%n)个结点组成的链表与前n-k个结点组成的链表互换

实现方法
  1. 统计链表结点个数,并且记录当前链表最后一个结点
  2. 计算确认k
  3. 找到前n-k个结点,确定新的第一个结点和最后一个结点
  4. 操作结点的next引用组成新链表
代码图示

上面实现方法第三步执行后,代码中的引用如图指向各个结点。第四步是分别操作链表两部分的指向关系。


image.png
代码
private class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}
public ListNode rotateRight(ListNode head, int k) {
    if(null == head || k <= 0){
        return head;
    }
    /*统计链表结点个数,并且记录当前链表最后一个结点*/
    ListNode tail = head;
    int n = 1;
    while(tail.next != null){
        tail = tail.next;
        n++;
    }
    /*计算确认k*/
    k = k % n;
    if(0 == k){
        return head;
    }
    /*找到前n-k个结点,确定新的第一个结点和最后一个结点*/
    ListNode newTail = head;
    for(int i = 1 ; i < n - k; ++i){
        newTail = newTail.next;
    }
    ListNode newHead = newTail.next;
    /*操作结点的next引用组成新链表*/
    newTail.next = null;
    tail.next = head;
    return newHead;
}

总结

一些看似很复杂的需求可能往往存在一些简单的解法。例如本例中,假如循环k次,每次把所有结点移动一位,这样实现起来会相当复杂,并且容易出错。而实际上找到其中规律,前n-k个结点组成的链表和后k个结点组成的链表交换位置即可,实现和编码都变得简单。因此在实际生产中需要不断总结,优化自己的代码质量和算法效率。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一些概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这...
    Winterfell_Z阅读 6,138评论 0 13
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,305评论 0 16
  • 目录 1、属性 2、链表和数组的区别 2.1、数组概述 2.2、数组和链表优缺点 2.3、链表和数组的比较 3、单...
    我哈啊哈啊哈阅读 2,884评论 1 41
  • 基本概念 链表的含义: 链表是一种用于存储数据集合的数据结构,具有以下属性 相邻元素之间通过指针相连 最后一个元素...
    古剑诛仙阅读 1,035评论 0 3
  • 五一我们放假了,妈妈带着我和妹妹还有姥姥姥爷一起去动物园玩,太开心了,动物园里有大象,猴子,老虎,黑熊等等,太多的...
    葛雨辰阅读 223评论 0 0