题目描述

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

示例1:
No.61 旋转链表 (Medium) - 图1

示例2:
No.61 旋转链表 (Medium) - 图2

思路

从示例2可以看出,k可能大于链表长度size, 也就是说,例如size = 3, k = 4时,向右移动4步,等价于向右移动1步,即真正移动的距离为k % size。

  1. 遍历链表,找到尾部tail以及算出链表长度size;
  2. tail指向head,形成环;
  3. 移动k个位置,即移动k % size 个位置,新的tail相当于往前移动了k % size个位置,从正向数的话,新的tail为head后面的第size - (k % size) - 1个结点。例如size = 7, k = 2,那么新的tail 是 7 往前移动2个位置,即5, 5 就是head往后移动 5 - 1的位置,
  4. 第3步找到了新的tail, 即newTail, 新的head即newTail的下一个结点,即newHead = newTail.next;
  5. 使得newTail.next指向null

代码

  1. class Solution {
  2. public ListNode rotateRight(ListNode head, int k) {
  3. // 空链表或者只有一个结点的链表
  4. if (head == null || head.next == null) {
  5. return head;
  6. }
  7. if (k == 0) {
  8. return head;
  9. }
  10. ListNode tail = head;
  11. // 因为tail和head指向同一个结点,此时链表长度为1
  12. int size = 1;
  13. // 这里不能判断tail == null, 因为tail == null时,tail = tail.next会报空指针异常
  14. // 建议画一个链表,更形象
  15. while (tail.next != null) {
  16. tail = tail.next;
  17. size++;
  18. }
  19. // 形成环
  20. tail.next = head;
  21. ListNode newTail = head;
  22. ListNode newHead = head;
  23. // 找到新的tail
  24. for (int i = 0; i < size - (k % size) - 1; i++) {
  25. newTail = newTail.next;
  26. }
  27. // 新的head
  28. // 因为最后要返回头结点,所以需要保存
  29. newHead = newTail.next;
  30. // 断开
  31. newTail.next = null;
  32. return newHead;
  33. }
  34. }