代码随想录第3天 | 203. 移除链表元素、707. 设计链表、206. 反转链表

文章介绍了链表中删除元素的两种方法,包括处理头节点的特殊情况和使用虚拟头节点简化操作。接着讨论了设计链表的五个接口,如插入、删除节点,并提供了JavaScript实现。最后,展示了两种反转链表的方法,分别是双指针法和递归法。
摘要由CSDN通过智能技术生成

203. 移除链表元素

  1. 原链表上删除元素:需要注意的是删除头节点的操作和删除其他元素的操作是不一样的。判断完头节点后再从头节点向后依次遍历链表中元素。
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {
    while(head !== null && head.val === val){
        head = head.next;
    }
    let cur = head;
    while(cur !== null && cur.next !== null){
        if(cur.next.val === val){
            cur.next = cur.next.next;
        }
        else{
            cur = cur.next;
        }
    }
    return head;
};
  1. 设置一个虚拟头节点再进行删除操作:这种方式不用再考虑头节点的特殊性,因为设置了虚拟头节点,依次向后遍历链表元素即可了。
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function (head, val) {
    let dummyHead = new ListNode(0, head);
    let cur = dummyHead;
    while (cur.next !== null) {
        if (cur.next.val === val) {
            cur.next = cur.next.next;
            continue;
        }
        cur = cur.next;
    }
    return dummyHead.next;

707. 设计链表

这道题目设计链表的五个接口:

  • 获取链表第index个节点的数值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点前面插入一个节点
  • 删除链表的第index个节点

首先要确定链表在JavaScript中的定义,构造一个ListNode类,再构造一个MyLinkedList类:

class LinkNode {
    constructor(val, next) {
        this.val = val;
        this.next = next;
    }
}

var MyLinkedList = function () {
    this._size = 0;
    this._head = null;
    this._tail = null;
};

注意
① index是从0开始还是从1开始;
② 头节点和尾节点的指定;
③ 链表元素个数,是否只有一个元素。

下面是具体的操作(先定义了一个获取index位置节点的函数,方便之后的操作):

/**
 * Get the value of the index-th node in the linked list. If the index is invalid, return -1. 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.getNode = function (index) {
    if (index < 0 || index >= this._size) return null;
    // 创建虚拟头节点
    let cur = new LinkNode(0, this._head);
    // 0 -> head
    while (index-- >= 0) {
        cur = cur.next;
    }
    return cur;
};

/** 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function (index) {
    if (index < 0 || index >= this._size) return -1;
    // 获取当前节点
    return this.getNode(index).val;
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function (val) {
    const node = new LinkNode(val, this._head);
    this._head = node;
    this._size++;
    if (!this._tail) {
        this._tail = node;
    }
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function (val) {
    const node = new LinkNode(val, null);
    this._size++;
    if (this._tail) {
        this._tail.next = node;
        this._tail = node;
        return;
    }
    this._tail = node;
    this._head = node;
};

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function (index, val) {
    if (index > this._size) return;
    if (index <= 0) {
        this.addAtHead(val);
        return;
    }
    if (index === this._size) {
        this.addAtTail(val);
        return;
    }
    const node = this.getNode(index - 1);
    node.next = new LinkNode(val, node.next);
    this._size++;
};

/** 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function (index) {
    if (index < 0 || index >= this._size) return;
    const node = this.getNode(index);
    if (index === 0) {
        this._head = this._head.next;
        if (index === this._size - 1) {
            this._tail = this._head;
        }
        this._size--;
        return;

    }
    let cur = this.getNode(index - 1);
    cur.next = cur.next.next;
    if (index === this._size - 1) {
        this._tail = cur;
    }
    this._size--;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * var obj = new MyLinkedList()
 * var param_1 = obj.get(index)
 * obj.addAtHead(val)
 * obj.addAtTail(val)
 * obj.addAtIndex(index,val)
 * obj.deleteAtIndex(index)
 */

206. 反转链表

  1. 双指针法:因为要反转链表,所以当前元素的next指针就要指向它的前一个元素。由此首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let cur = head;
    let pre = null;
    while(cur){
        temp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = temp;
    }
    return pre;
};
  1. 递归法:根据循环来写递归。同样是当cur为空的时候循环结束,不断将cur指向pre的过程。
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    return reverse(head, null);
};

var reverse = function(cur, pre){
    if(!cur) return pre;
    let temp = cur.next;
    cur.next = pre;
    return reverse(temp, cur);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值