算法题之旋转链表

旋转链表

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

示例 1:

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

示例 2:

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

提示:

  • 链表中节点的数目在范围 [0, 500] 内
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109

解题思路

从题目的要求来看,我们需要将整条链表往右移动k个位置;也就是会把链表尾部的k个节点,依次往链表头上添加,在提示中,给出了链表值的范围,其实这个条件是无效的,因为,我们不会对链表的值进行操作,有用的条件是提示中的链表的节点数和k的取值范围。

我们确定解题思路:首先我们先将链表首尾相连,然后按照要求,依次遍历节点,截断位置。那么应该截断的位置在哪里呢?我们推导一下:

  • 如示例1,总共5个节点,向右移动2个位置;最后,链表首位是第4个节点,链表尾部是第3个节点,所以需要遍历到第5 - 2 = 3个节点作为尾部,下一个节点作为头部。
  • 如示例2,总共3个元素,向右移动4个位置,这个时候注意,移动的位置数是大于链表的长度的;如果我们移动3个位置,相当于不变,所以移动4个位置相当于是只移动了4 - 3 = 1个位置;所以需要遍历到第(3 - 4%3)= 2个节点作为尾部,下一个节点作为头部。

具体代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {

        if(head == null || head.next == null || k == 0)return head;

        int len = 0;
        ListNode node = head;

        // 遍历链表尾部
        for(len = 1; node.next != null; len++)node = node.next;
        node.next = head; // 首尾相连

        ListNode pre = head;

        for(int i = 1; i < len - k%len; i++)pre = pre.next;
        head = pre.next;
        pre.next = null;

        return head;
    }
}

复杂度分析

  • 时间复杂度:O(n),我们最少也需要遍历链表一次;最糟糕的情况下,当链表的长度n等于k+1时,我们需要遍历链表n + n - 1次。
  • 空间复杂度:O(1),我们只需要常数的空间,来存储len、node、pre即可。
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值