用JavaScript写 203.移除链表元素 707.设计链表 206.反转链表 | 代码随想录训练营Day3

77 阅读2分钟

203.移除链表元素

本题要点

①未添加虚拟头节点,需要分类讨论空头指针;

②添加虚拟头节点,可以直接遍历链表。

对方法2的补充:

假设样例为[7,7,8,8] val = 7

这种情况下return head 的结果是[7,7,8,8] 而不是理想的[8,8]

原因是 我们修改的是虚拟节点的next 而当第一个节点需要删除时,我们直接跳过了head.next的修改 就会导致开头连续或单个的7还是被输出 所以我们应该返回 dummyHead.next

代码实现

对原链表进行操作

function removeElements(head: ListNode | null, val: number): ListNode | null {
  // 对原链表直接进行操作
  // 头节点的删除操作(特殊)
  while(head !== null && head.val === val){
    head = head.next
    // JS不用手动进行删除节点的操作,有浏览器的回收机制 
  }
  // 非头节点的删除操作
  let cur: ListNode  = null
  cur = head
  while(cur !== null && cur.next !== null){
    if(cur.next.val === val){
      cur.next = cur.next.next
      // 最开始写错了,写了cur = cur.next.next
    } else {
      cur = cur.next
    }
  }
  return head
};

新增一个虚拟头节点

function removeElements(head: ListNode | null, val: number): ListNode | null {
  let dummyHead: ListNode = new ListNode(0, head)
  let cur = dummyHead
  // dummyHead为引入的虚拟头节点
  while(cur !== null && cur.next !== null){
    if(cur.next.val === val){
      // console.log('=' + cur.next.val)
      cur.next = cur.next.next
    } else {
      // console.log('!=' + cur.next.val)
      cur = cur.next
    }
  }
  return dummyHead.next
  // 这里不直接返回head是因为有些特殊情况里
  // 我们没有修改过head.next等后续链表节点指向
  // 详细说明见上面思路分析部分
};

707.设计链表

本题要点

要点看代码中的注释

代码实现

class MyListNode {
  public val: number;
  public next: ListNode | null;
  constructor(val?: number, next?: ListNode | null) {
    this.val = val === undefined ? 0 : val;
    this.next = next === undefined ? null : next;
  }
}
​
class MyLinkedList {
  private size: number;
  private head: ListNode;
  private tail: ListNode;
  constructor() {
    this.size = 0;
    this.head = null;
    this.tail = null;
  }
​
  // 抽象出新的函数
  getNode(index: number):ListNode {
    // 引入虚拟头节点
    let dummyHead: ListNode = new ListNode(0, this.head);
    // 添加指针循环链表
    let cur = dummyHead;
    for (let i = 0; i <= index; i++) {
      // 理论上不会出现 null
      cur = cur.next!;
    }
    return cur;
  }
​
  get(index: number): number {
    // 判断index的有效性
    if(index < 0 || index >= this.size){
      return -1;
    }
    let cur = this.getNode(index);
    return cur.val;
  }
​
  addAtHead(val: number): void {
    let node: ListNode = new ListNode(val, this.head);
    this.head = node;
    this.size++;
    // 如果当前还没有尾节点(也就是说当前链表为空),将尾节点也设置为node
    if(!this.tail){
      this.tail = node;
    }
  }
​
  addAtTail(val: number): void {
    let node: ListNode = new ListNode(val, null);
    if(this.tail){
      this.tail.next = node;
    } else {
      // 同上 如果没有尾节点说明链表为空,设置头节点
      this.head = node;
    }
    this.tail = node;
    this.size++;
  }
​
  addAtIndex(index: number, val: number): void {
    // 首先用条件判断来写题目中给出的特殊情况
    if(index === this.size){
      this.addAtTail(val);
      return;
    }
    if(index > this.size){
      return;
    }
    if(index <= 0){
      this.addAtHead(val);
      return;
    }
    // 获取第index个节点的前一个(改变其next指向来实现插入)
    let cur = this.getNode(index - 1);
    let node: ListNode = new ListNode(val, cur.next);
    cur.next = node;
    this.size++;
  }
​
  deleteAtIndex(index: number): void {
    // 判断index的有效性
    if(index < 0 || index >= this.size){
      return;
    }
    if(index === 0){
      this.head = this.head.next;
      if(this.size === 1){
        this.tail = null;
      }
      this.size--;
      return;
    }
    // 处理其他情况
    let cur = this.getNode(index - 1);
    cur.next = cur.next.next
    if(index === this.size - 1){
      this.tail = cur;
    }
    this.size--;
  }
}
​

206.反转链表

本题要点

本题有两种实现方式,第一种是结合双指针的常规的写法,第二种是递归写法。

代码实现

双指针法

function reverseList(head: ListNode | null): ListNode | null {
  let cur = null, pre = null, temp = null;
  pre = head;
  while(pre){
    temp = pre.next;
    pre.next = cur;
    cur = pre;
    pre = temp;
  }
  return cur
};

递归写法

function reverseList(head: ListNode | null): ListNode | null {
  function reverse(pre: ListNode | null, cur: ListNode | null): ListNode | null {
    if (cur === null) return pre
    let temp: ListNode | null = null
    temp = cur.next
    cur.next = pre
    pre = cur
    cur = temp
    return reverse(pre, cur)
  }
  return reverse(null, head)
};