代码随想录算法训练营第三天| 203.移除链表元素、707.设计链表、 206.反转链表

203.移除链表元素

题目链接:203.移除链表元素

文档讲解:代码随想录/移除链表元素

视频讲解:视频讲解-移除链表元素

状态:已完成(2遍)

解题过程 

看到题目的第一想法

 半路出家学前端、做前端项目0.6坤年,没用过链表,故没有想法。

但我GPT了一下:

在 JavaScript 中,我们可以使用对象和引用来实现链表的基本结构。具体实现如下:

首先,我们需要定义一个链表节点的构造函数。每个节点包含两个属性:value 用于存储节点的值,next 用于存储指向下一个节点的引用。

class ListNode {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

//接下来,我们可以通过创建节点对象并设置它们的 next 属性来构建链表。链表的头节点表示链表的起始点。

const node1 = new ListNode(1);
const node2 = new ListNode(2);
const node3 = new ListNode(3);

node1.next = node2;
node2.next = node3;

看完代码随想录之后的想法 

讲解中讲了虚拟头结点的方法,非常简便,另一种分情况判断的方法在文字讲解中的JS部分也没有,索性就只研究这个方法好了。通过在现有头结点前再设一个虚拟头结点,可以很好的统一后续对所有节点的判断流程,值得注意的是虚拟头结点的值在此时是不重要的。看完视频和文字讲解之后手搓了一版问题不大。

/**
 * 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 visHead = new ListNode(0,head);//定义一个哨兵头结点,方便统一删除的操作,哨兵节点的next指向head
    let cur = visHead;
    while(cur.next){//当next不为空时
        if(cur.next.val===val){//如果值是val
            cur.next=cur.next.next;//当前节点的next直接指向当前节点的next的next
            continue;
        }
        cur = cur.next;//如果值不等于val,当前节点跳到下一个节点
    }
    return visHead.next;
};

总结

确实是第一次认识链表,感觉今天和明天是极其艰难的两天,一点点啃下来吧。

二刷把continue忘了可还行。。


 707.设计链表

题目链接:707.设计链表

文档讲解:代码随想录/设计链表

视频讲解:视频讲解-设计链表

状态:已完成(2遍)

解题过程  

看到题目的第一想法

这题目看的前端真的很头疼,放弃思考,躺平看讲解。

 看完代码随想录之后的想法 

视频部分的讲解倒是不太难,但是文字讲解一上来的定义链表部分的代码就给我干懵了。。

今天时日已晚,待我周末再细细研究一下其中奥妙,我一定会回来的!

昨天代码看的晕乎的,我还在想JS有什么神通能知道我定义的size、head、tail有什么功能,今天一细看,嗷,原来他的功能是自己会在下面规定的,那没事了。

这里定义一个虚拟头结点还是好用,爱用,多用。

头部插入节点的时候一定要注意先让newnode.next = dummyhead.next!不管是什么情况下的插入节点,一定要弄清楚cur该指向什么节点。 

class LinkNode {
    constructor(val, next) {
        this.val = val;
        this.next = next;
    }
}
var MyLinkedList = function() {
    this._size = 0;
    this._tail = null;
    this._head = null;
};

/** 
 * @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;
};
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;
    if(index === 0) {
        this._head = this._head.next;
        // 如果删除的这个节点同时是尾节点,要处理尾节点
        if(index === this._size - 1){
            this._tail = this._head
        }
        this._size--;
        return;
    }
    // 获取目标节点的上一个的节点
    const node = this.getNode(index - 1);    
    node.next = node.next.next;
    // 处理尾节点
    if(index === this._size - 1) {
        this._tail = node;
    }
    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)
 */

总结

通过这道题认识了链表的一些基本操作背后的原理,但是JS定义链表的部分还需要继续研究。


 206.反转链表

题目链接:206.反转链表

文档讲解:代码随想录/反转链表

视频讲解:视频讲解-反转链表

状态:已完成(2遍)

解题过程  

看到题目的第一想法

想了一会脑子里蹦出来的解法全是关于数组的,链表真得狠狠学一下吧,对解题一点思路没有,很崩溃。。。

 看完代码随想录之后的想法 

卧槽,这反转链表真有意思,要是我能学会就更有意思了,不多bb,上手操作一下反转next的方向。

看了视频和文字讲解之后手搓一版:

/**
 * 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) {
    if(!head || !head.next) return head;
    let temp = null, pre = null, cur = head;
    while(cur) {
        temp = cur.next;//临时保存当前节点的下一个节点
        cur.next = pre;//调转方向的一步
        pre = cur;//上一个节点移到当前节点
        cur = temp;//当前节点移到下一个节点
    }
    return pre;
};

总结

初次接触链表,进度进行得如陷入泥泞般困难,今天跟着讲解之后敲一遍代码,尝试着理解但理解没多少,明天立马再次二刷。

二刷完毕,总算是有点进步,看Day04任务去了。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值