攻克代码随想录Day3(JavaScript) | 203. 移除链表元素 | 707. 设计链表 | 206. 反转链表

一、203. 移除链表元素

今天我们开始进入链表的学习。首先我们先要明确链表的一个重要的特点:易增删,难查找,这和数组形成了明显的区别:易查找,难增删
明确了这一点后,我们就可以开始做题了!移除链表元素的原理很简单,就是把指向下个节点的指针移到下下个节点上,具体代码如下:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {
    const dummy = new ListNode(0,head);
    let cur = dummy;
    while(cur.next){
        if(cur.next.val === val){
            cur.next = cur.next.next;
            continue;
        }
        cur = cur.next;
    }
    return dummy.next;
};

由上可见,我们首先声明了一个dummy的常量,为一个虚拟头节点,该节点可以帮助我们解决需要删除原头节点的问题,之后便开始我们的删除操作了。值得注意的是,在while循环中将当前链表的指针域改为指向下下个节点时,需要在后面添加一行continue;否则,如果下下个节点是空值则将报错,且这种情况也会导致无法删除连续的两个节点

二、707. 设计链表

说句实话,这真是一道既耗费时间又耗费精力的题:5个函数且函数之间还得经常互相调用,代码量是比较大的。具体代码如下:

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

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

/** 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.getNode = function(index){
    if(index < 0 || index >= this._count){
        return null;
    }
    let cur = new ListNode(0,this._head);
    while(index-- >= 0){
        cur = cur.next;
    }
    return cur;

}

MyLinkedList.prototype.get = function(index) {
    if(index < 0 || index >= this._count) return -1;
    return this.getNode(index).val;
};

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

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function(val) {
    if(this._count === 0){
        const newNode = new ListNode(val,null);
        this._count++;
        this._head = newNode;
        this._tail = newNode;
        return;
    }
    const newNode = new ListNode(val,null);
    let cur = this.getNode(this._count - 1);
    cur.next = newNode;
    this._tail = newNode;
    this._count++;
};

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function(index, val) {
    if(index > this._count){
    }
    else if(index <= 0){
        this.addAtHead(val);
    }
    else if(index === this._count){
        this.addAtTail(val);
    }
    else{
        let cur = this._head;
        while(index-- >= 2){
            cur = cur.next;
        }
        const newNode = new ListNode(val,cur.next);
        cur.next = newNode;
        this._count++;
    }
};

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

/**
 * 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)
 */

在代码的开头,先对节点和链表进行定义。定义完后先设计一个getNode()的函数,对于不符合规范的index返回空值,而符合规范的返回节点值。因此,get()函数就只用调用getNode()函数并获取其val属性就行。addAtHead()函数要增加1个链表长度,并将_head属性指向新节点,如果原本_tail属性为null,则_tail属性也得更改。addAtTail()函数设计方式也十分类似。addAtIndex()函数得先排除几种特殊情况,然后通过迭代找到所需的节点,并在后面增加新的节点。deleteAtIndex()也得分删除头节点和删除其余节点的情况。该题难度主要是函数太多,写错一步就步步错,但是这道题作为对链表知识的理解还是非常重要的。

三、206. 反转链表

反转链表不是很难,但是很注重细节,具体代码如下:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let cur = head;
    let temp = null;
    let fast = null;
    while(cur){
        fast = cur.next;
        cur.next = temp;
        temp = cur;
        cur = fast;
    }
    return temp;
};

首先先声明cur指向头节点,然后声明两个temp,fast当辅助节点。当cur存在时,fast指向cur指针指向的下一个节点,而cur指针这时候指向一个空节点,然后cur的值将会被赋给temp而fast的值将会被赋值给cur(相当于指针集体往后移一个位置),以此内推直至cur指向null,这时候我们的temp就是头节点,返回就完事了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值