每日一道算法 Day7

123 阅读1分钟

题目描述:

截屏2021-08-02 下午9.49.12.png

第一种思路:

先扫描链表一次拿到链表长度, 然后再扫描一边通过n拿到需要移出掉的节点的前一位target, 然后设置target.next = target?.next?.next ?? null, 得到结果。 完整代码如下

export function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
  if (!head || !head.next) return null;
  //head 长度
  let length = 1;
  let target = null;
  let next = head;
  while (next.next) {
    next = next.next as any;
    length++;
  }
  let next2 = new ListNode();
  next2 = head;
  for (let i = 0; i < length; ++i) {
    if (i === length - n - 1) {
      target = new ListNode();
      target = next2;
    }
    next2 = next2?.next!;
  }
  if (!!target) {
    target.next = target?.next?.next ?? null;
  } else {
    return head.next;
  }

  return head;
}

第二种思路: 快慢指针

创建快慢两个指针, 快指针先走n步, 然后快慢指针同时开始走, 当快指针走到尾时, 慢指针指向位置为需要移出掉的前一位, 然后同样设置target.next = target?.next?.next ?? null, 得到结果。该方法只需扫描一次链表。

代码如下:

export function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
  if (!head || !head.next) return null;
  //快指针
  let fast = head;
  //慢指针
  let slow = head;
  while (n--) {
    //先将快指针 走 n 步
    if (!fast.next) {
      return head.next;
    }
    fast = fast.next;
  }
  while (fast.next) {
    fast = fast.next;
    slow = slow.next!;
  }
  slow.next = slow.next!.next;
  return head;
}