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任务去了。