每日一道算法Day32-- 旋转链表

161 阅读1分钟

题目描述

image.png

大致思路

  1. 情况分为两种, 链表长度大于k和链表长度小于k时(相等的情况直接返回head)
  2. 小于时, 旋转后的链表的头节点为原链表的倒数第k位, 然后将原链表的尾部与头部相连
  3. 大于时, 旋转后的链表的头节点为原链表的倒数第(k % len, k % len为0时, 与相等的情况相同)位, 然后将原链表的尾部与头部相连.

代码如下:

function rotateRight(head: ListNode | null, k: number): ListNode | null {
  //边界情况判断
  if (head === null || k === 0) {
    return head;
  }

  //获取链表长度
  let len = 1;
  let lenTmp = head;
  let res = new ListNode();
  while (lenTmp.next) {
    lenTmp = lenTmp.next;
    len++;
  }
  //当长度相等或者链表长度为1时, 直接返回head
  if (len === k || len === 1) {
    return head;
  }
  //获取旋转后排在头部的序号
  let sum = k > len ? k % len : k;

  //为0时, 也直接返回head
  if (sum === 0) {
    return head;
  }

  /**
   * 利用快慢指针拿到倒数第 sum 的节点
   */
  let fast = head;
  let slow = head;
  while (sum > 0) {
    fast = fast.next!;
    sum--;
  }

  /**
   * p1 为头部节点, p2为头部前一个
   */
  while (fast.next) {
    fast = fast.next;
    slow = slow.next!;
  }
  // 获取头部节点
  res = slow.next!;
  //将head后半部分置空
  slow.next = null;

  console.log(res, slow);
  let tmp = res!;
  while (tmp.next) {
    tmp = tmp?.next;
  }
  //拼接后半部分
  tmp.next = head;

  return res;
}