-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 115 题:写一个单向链数据结构的 js 实现并标注复杂度 #226
Comments
class LinkList {
constructor() {
this.head = null
}
find(value) {
let curNode = this.head
while (curNode.value !== value) {
curNode = curNode.next
}
return curNode
}
findPrev(value) {
let curNode = this.head
while (curNode.next!==null && curNode.next.value !== value) {
curNode = curNode.next
}
return curNode
}
insert(newValue, value) {
const newNode = new Node(newValue)
const curNode = this.find(value)
newNode.next = curNode.next
curNode.next = newNode
}
delete(value) {
const preNode = this.findPrev(value)
const curNode = preNode.next
preNode.next = preNode.next.next
return curNode
}
}
class Node {
constructor(value, next) {
this.value = value
this.next = null
}
} |
问题来了,在哪学数据结构相关知识 |
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class SinglyLinkedList {
#firstNode;
constructor() {
this.#firstNode = null;
}
get firstNode() {
return this.#firstNode;
}
insertAfter(node, newNode) {
if (!newNode) return;
if (node) {
newNode.next = node.next;
node.next = newNode;
}
else {
newNode.next = this.#firstNode;
this.#firstNode = newNode;
}
}
insertBeginning(newNode) {
this.insertAfter(null, newNode);
}
removeAfter(node) {
if (node) {
node.next = node.next.next;
}
else if (this.#firstNode) {
this.#firstNode = this.#firstNode.next;
}
}
removeBeginning() {
this.removeAfter(null);
}
}
var list = new SinglyLinkedList();
list.insertBeginning(new Node("a"));
list.insertAfter(list.firstNode, new Node("d"));
list.insertAfter(list.firstNode, new Node("c"));
list.insertAfter(list.firstNode, new Node("b"));
var currentNode = list.firstNode;
while (currentNode) {
console.log(currentNode.data);
currentNode = currentNode.next;
}
list.removeBeginning(); // Remove 'a'
list.removeAfter(list.firstNode); // Remove 'c' after 'b'
var currentNode = list.firstNode;
while (currentNode) {
console.log(currentNode.data);
currentNode = currentNode.next;
} |
class ListNode {
constructor(val) {
this.val = val
this.next = null
}
}
class LinkedList {
head = null
tail = null
size = 0
// 时间复杂度O(n)
get = index => {
if (index < 0) return -1
let node = this.head
for (let i = 0; i < index; i++) {
if (!node) return -1
node = node.next
}
return node ? node.val : -1
}
// 时间复杂度O(1)
addAtHead = val => {
const node = new ListNode(val)
if (!this.head) {
this.head = this.tail = node
} else {
node.next = this.head
this.head = node
}
this.size++
}
// 时间复杂度O(1)
addAtTail = val => {
const node = new ListNode(val)
if (!this.tail) {
this.head = this.tail = node
} else {
this.tail.next = node
this.tail = node
}
this.size++
}
// 时间复杂度O(n)
addAtIndex = (index, val) => {
const node = new ListNode(val)
if (index > this.size) return
if (index === this.size) return this.addAtTail(val)
if (index <= 0) return this.addAtHead(val)
let head = this.head
for (let i = 1; i < index; i++) {
if (!head) return
head = head.next
}
node.next = head.next
head.next = node
this.size++
}
// 时间复杂度O(n)
deleteAtIndex = index => {
let head = this.head
if (!head || index >= this.size || index < 0) return
if (index === 0) {
if (this.size === 1) {
this.head = this.tail = null
} else {
this.head = this.head.next
}
this.size--
return
}
for (let i = 1; i < index; i++) {
if (!head) return
head = head.next
}
if (!head) return
if (head.next) {
if (head.next === this.tail) {
this.tail = head
head.next = null
} else {
head.next = head.next.next
}
} else {
this.head = this.tail = null
}
this.size--
}
} |
|
我删除node的时候假如把head传进去,这个方法就不对了 |
神仙题,,,看不懂咋办 |
//链表节点 //链表
} 正好学习的时候照着写过,不过时间复杂度和空间复杂度我都不太懂💔 |
那就多学呗,#156 (comment) |
看不懂,从哪学习这些链表啥的基础知识 |
|
class Node { class LinkList {
} |
常规的解法就是增删改查,修改next的指向和value值或者删除增加节点。这里不再走寻常路。维护一个数组,通过代理数组操作返回链表。数组<item, index, array>型的api基本都是O(n)时间复杂度和O(1)空间复杂度,但是这里最后会有一个全部遍历同步的操作,额外稳定增加O(n)时间复杂度。如果想做到O(1)复杂度的修改,则需要劫持每一个数组操作,并利用额外缓存存下各种信息,大约还需要O(n)空间复杂度才能换取O(1)的时间复杂度 class LinkList {
constructor(...args) {
this.temp = []
this.temp.push(...args)
}
}
function createLinkList(...init) {
const ret = new LinkList(...init)
let current
const result = ret.temp.reduce((res, cur) => {
current = current || res
current.value = cur
current.next = current.next || {}
current = current.next
return res
}, Object.create(new Proxy(ret.temp, {
get(target, name) {
const record = Reflect.get(target, name)
if (typeof record === 'function') {
return (...args) => {
const retVal = Reflect.apply(record, target, args)
let current = result
ret.temp.forEach(item => {
current.value = item
current = current.next || {}
})
return retVal
}
}
return record
}
})))
return result
}
const mockLinkList = createLinkList(1,2,3)
mockLinkList.push(1, 2)
mockLinkList.pop()
// ......所有的数组操作 |
|
|
// 单向 class Node{
//////////////////////////////////////////////////////////////////////////////
复杂度O(n) |
class Node{
constructor(data){
this.data=data
this.next=null
}
}
class LinkedList{
constructor(){
this.head=null
this.tail=null
}
push(data){
const node=new Node(data)
if(!this.head){
this.head=node
this.tail=node
}
this.tail.next=node
this.tail=node
}
...
} |
class Node {
constructor(val){
this.val = val;
this.next = null
}
}
class NodeList{
constructor(array){
array.forEach((val,index)=>{
index == 0?this.head = new Node(val) : this.insertNewNode(val)
})
}
insertNewNode(val){
let cur = this.head ;
while(cur.next){
cur = cur.next
}
cur.next = new Node(val)
}
/**
* ohter methods
* ...
* ...
* ..
* */
} |
今天又流下了眼泪,单向链数据结构是啥我都不知道 |
find 中,curnode.next =null 时,null.value 是会报错的---》 |
链表没有随机访问的能力,获取第n个元素需要从第一个元素逐步查询 const LinkList = (function () {
class _Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkList {
constructor() {
this.head = null;
}
find(val) {
let node = this.head;
while (node && node.value !== val) {
node = node.next;
}
return node;
}
findPre(val) {
let node = this.head;
while (node) {
if (node.next && node.next.value === val) {
break;
}
node = node.next;
}
return node;
}
delete(val) {
let preNode = this.findPre(val);
let curNode;
if (preNode) {
curNode = preNode.next;
preNode.next = curNode.next;
}
else {
curNode = this.find(val);
if (curNode) {
this.head = curNode.next;
}
}
return curNode;
}
unshift(val) {
let node = new _Node(val);
let first = this.head;
if (!first)
this.head = node;
else {
node.next = first;
this.head = node;
}
return node;
}
push(val) {
let node = new _Node(val);
let curNode = this.head;
while (curNode && curNode.next) {
curNode = curNode.next;
}
!curNode ? this.head = node : curNode.next = node;
return node;
}
insert(newValue, value) {
let newNode = new _Node(newValue);
let curNode = this.find(value);
if (!curNode)
this.unshift(newValue);
else {
newNode.next = curNode.next;
curNode.next = newNode;
}
return newNode;
}
}
return LinkList;
}()); |
直接一个单链表给他甩脸上 |
// 单向链表
class ListNode{
constructor(val, next=null){
this.val = val
this.next = next
}
}
class List {
#head = null;
#size = 0;
// 末尾追加节点
appendNode(newNode){
if(this.isEmpty()){
this.#head = newNode
} else {
let tail = this.#head;
while(tail.next){
tail = tail.next
}
tail.next = newNode
}
this.#size ++
}
// 指定节点前面插入节点
insertBefore(newNode, referenceNode){
if(!referenceNode) return false
if(this.isEmpty()) return false
// 插入头节点前面
if(referenceNode === this.#head){
newNode.next = this.#head
this.#head = newNode
this.#size ++
return
}
// 插入其他节点前面
let prev = this._findPrevNode(referenceNode)
if(!prev) return false
prev.next = newNode
newNode.next = referenceNode
this.#size ++
return true
}
// 删除指定节点
removeNode(node){
if(!node) return false
if(this.isEmpty()) return false
// 删除头节点
if(node === this.#head){
this.#head = node.next;
node.next = null
this.#size --
return true
}
// 删除其他节点
let prev = this._findPrevNode(node)
if(!prev) return false
prev.next = node.next
node.next = null
this.#size --
return true
}
// 按值查找节点
findNodeByVal(val){
let node = this.#head
while(node){
if(node.val === val){
return node
}
node = node.next
}
return null
}
// 查找节点前面的邻居
_findPrevNode(node){
if(this.isEmpty()) return null
let prev = this.#head;
while(prev.next!==node){
prev = prev.next;
}
if(prev.next === node){
return prev
}
return null
}
// 是否为空
isEmpty(){
return this.#head === null
}
// 获取链表长度
size(){
return this.#size
}
} |
问这样的问题不知道是出于什么考虑的? |
No description provided.
The text was updated successfully, but these errors were encountered: