Skip to content

Commit 3f1444e

Browse files
author
liguanliang1
committed
feat: link-list
1 parent 95b77d3 commit 3f1444e

File tree

5 files changed

+421
-1
lines changed

5 files changed

+421
-1
lines changed

leetcode/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ import "./rotateListNode"
1919
import "./searchWord"
2020
import "./stringCalculate"
2121
import "./MathSqrt"
22-
import "./search-binary-tree/index"
22+
import "./search-binary-tree/index"
23+
import "./link-list/rotateList"

leetcode/link-list/Comparator.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
export default class Comparator {
2+
/**
3+
* Constructor.
4+
* @param {function(a: *, b: *)} [compareFunction] - It may be custom compare function that, let's
5+
* say may compare custom objects together.
6+
*/
7+
constructor(compareFunction) {
8+
this.compare = compareFunction || Comparator.defaultCompareFunction;
9+
}
10+
11+
/**
12+
* Default comparison function. It just assumes that "a" and "b" are strings or numbers.
13+
* @param {(string|number)} a
14+
* @param {(string|number)} b
15+
* @returns {number}
16+
*/
17+
static defaultCompareFunction(a, b) {
18+
if (a === b) {
19+
return 0;
20+
}
21+
22+
return a < b ? -1 : 1;
23+
}
24+
25+
/**
26+
* Checks if two variables are equal.
27+
* @param {*} a
28+
* @param {*} b
29+
* @return {boolean}
30+
*/
31+
equal(a, b) {
32+
return this.compare(a, b) === 0;
33+
}
34+
35+
/**
36+
* Checks if variable "a" is less than "b".
37+
* @param {*} a
38+
* @param {*} b
39+
* @return {boolean}
40+
*/
41+
lessThan(a, b) {
42+
return this.compare(a, b) < 0;
43+
}
44+
45+
/**
46+
* Checks if variable "a" is greater than "b".
47+
* @param {*} a
48+
* @param {*} b
49+
* @return {boolean}
50+
*/
51+
greaterThan(a, b) {
52+
return this.compare(a, b) > 0;
53+
}
54+
55+
/**
56+
* Checks if variable "a" is less than or equal to "b".
57+
* @param {*} a
58+
* @param {*} b
59+
* @return {boolean}
60+
*/
61+
lessThanOrEqual(a, b) {
62+
return this.lessThan(a, b) || this.equal(a, b);
63+
}
64+
65+
/**
66+
* Checks if variable "a" is greater than or equal to "b".
67+
* @param {*} a
68+
* @param {*} b
69+
* @return {boolean}
70+
*/
71+
greaterThanOrEqual(a, b) {
72+
return this.greaterThan(a, b) || this.equal(a, b);
73+
}
74+
75+
/**
76+
* Reverses the comparison order.
77+
*/
78+
reverse() {
79+
const compareOriginal = this.compare;
80+
this.compare = (a, b) => compareOriginal(b, a);
81+
}
82+
}

leetcode/link-list/LinkedList.js

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
import LinkedListNode from './LinkedListNode';
2+
import Comparator from './Comparator';
3+
4+
export default class LinkedList {
5+
/**
6+
* @param {Function} [comparatorFunction]
7+
*/
8+
constructor(comparatorFunction) {
9+
/** @var LinkedListNode */
10+
this.head = null;
11+
12+
/** @var LinkedListNode */
13+
this.tail = null;
14+
15+
this.compare = new Comparator(comparatorFunction);
16+
}
17+
18+
/**
19+
* @param {*} value
20+
* @return {LinkedList}
21+
*/
22+
prepend(value) {
23+
// Make new node to be a head.
24+
const newNode = new LinkedListNode(value, this.head);
25+
this.head = newNode;
26+
27+
// If there is no tail yet let's make new node a tail.
28+
if (!this.tail) {
29+
this.tail = newNode;
30+
}
31+
32+
return this;
33+
}
34+
35+
/**
36+
* @param {*} value
37+
* @return {LinkedList}
38+
*/
39+
append(value) {
40+
const newNode = new LinkedListNode(value);
41+
42+
// If there is no head yet let's make new node a head.
43+
if (!this.head) {
44+
this.head = newNode;
45+
this.tail = newNode;
46+
47+
return this;
48+
}
49+
50+
// Attach new node to the end of linked list.
51+
this.tail.next = newNode;
52+
this.tail = newNode;
53+
54+
return this;
55+
}
56+
57+
/**
58+
* @param {*} value
59+
* @return {LinkedListNode}
60+
*/
61+
delete(value) {
62+
if (!this.head) {
63+
return null;
64+
}
65+
66+
let deletedNode = null;
67+
68+
// If the head must be deleted then make next node that is different
69+
// from the head to be a new head.
70+
while (this.head && this.compare.equal(this.head.value, value)) {
71+
deletedNode = this.head;
72+
this.head = this.head.next;
73+
}
74+
75+
let currentNode = this.head;
76+
77+
if (currentNode !== null) {
78+
// If next node must be deleted then make next node to be a next next one.
79+
while (currentNode.next) {
80+
if (this.compare.equal(currentNode.next.value, value)) {
81+
deletedNode = currentNode.next;
82+
currentNode.next = currentNode.next.next;
83+
} else {
84+
currentNode = currentNode.next;
85+
}
86+
}
87+
}
88+
89+
// Check if tail must be deleted.
90+
if (this.compare.equal(this.tail.value, value)) {
91+
this.tail = currentNode;
92+
}
93+
94+
return deletedNode;
95+
}
96+
97+
/**
98+
* @param {Object} findParams
99+
* @param {*} findParams.value
100+
* @param {function} [findParams.callback]
101+
* @return {LinkedListNode}
102+
*/
103+
find({ value = undefined, callback = undefined }) {
104+
if (!this.head) {
105+
return null;
106+
}
107+
108+
let currentNode = this.head;
109+
110+
while (currentNode) {
111+
// If callback is specified then try to find node by callback.
112+
if (callback && callback(currentNode.value)) {
113+
return currentNode;
114+
}
115+
116+
// If value is specified then try to compare by value..
117+
if (value !== undefined && this.compare.equal(currentNode.value, value)) {
118+
return currentNode;
119+
}
120+
121+
currentNode = currentNode.next;
122+
}
123+
124+
return null;
125+
}
126+
127+
/**
128+
* @return {LinkedListNode}
129+
*/
130+
deleteTail() {
131+
const deletedTail = this.tail;
132+
133+
if (this.head === this.tail) {
134+
// There is only one node in linked list.
135+
this.head = null;
136+
this.tail = null;
137+
138+
return deletedTail;
139+
}
140+
141+
// If there are many nodes in linked list...
142+
143+
// Rewind to the last node and delete "next" link for the node before the last one.
144+
let currentNode = this.head;
145+
while (currentNode.next) {
146+
if (!currentNode.next.next) {
147+
currentNode.next = null;
148+
} else {
149+
currentNode = currentNode.next;
150+
}
151+
}
152+
153+
this.tail = currentNode;
154+
155+
return deletedTail;
156+
}
157+
158+
/**
159+
* @return {LinkedListNode}
160+
*/
161+
deleteHead() {
162+
if (!this.head) {
163+
return null;
164+
}
165+
166+
const deletedHead = this.head;
167+
168+
if (this.head.next) {
169+
this.head = this.head.next;
170+
} else {
171+
this.head = null;
172+
this.tail = null;
173+
}
174+
175+
return deletedHead;
176+
}
177+
178+
/**
179+
* @param {*[]} values - Array of values that need to be converted to linked list.
180+
* @return {LinkedList}
181+
*/
182+
fromArray(values) {
183+
values.forEach((value) => this.append(value));
184+
185+
return this;
186+
}
187+
188+
/**
189+
* @return {LinkedListNode[]}
190+
*/
191+
toArray() {
192+
const nodes = [];
193+
194+
let currentNode = this.head;
195+
while (currentNode) {
196+
nodes.push(currentNode);
197+
currentNode = currentNode.next;
198+
}
199+
200+
return nodes;
201+
}
202+
203+
/**
204+
* @param {function} [callback]
205+
* @return {string}
206+
*/
207+
toString(callback) {
208+
return this.toArray().map((node) => node.toString(callback)).toString();
209+
}
210+
211+
/**
212+
* Reverse a linked list.
213+
* @returns {LinkedList}
214+
*/
215+
reverse() {
216+
let currNode = this.head;
217+
let prevNode = null;
218+
let nextNode = null;
219+
220+
while (currNode) {
221+
// Store next node.
222+
nextNode = currNode.next;
223+
224+
// Change next node of the current node so it would link to previous node.
225+
currNode.next = prevNode;
226+
227+
// Move prevNode and currNode nodes one step forward.
228+
prevNode = currNode;
229+
currNode = nextNode;
230+
}
231+
232+
// Reset head and tail.
233+
this.tail = this.head;
234+
this.head = prevNode;
235+
236+
return this;
237+
}
238+
}
239+
// 兆易创新/紫光国微,复星医药/新和成,迈瑞医疗,隆基股份/金风科技,国轩高科/阳光电源

leetcode/link-list/LinkedListNode.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default class LinkedListNode {
2+
constructor(value, next = null) {
3+
this.value = value;
4+
this.next = next;
5+
}
6+
7+
toString(callback) {
8+
return callback ? callback(this.value) : `${this.value}`;
9+
}
10+
}

0 commit comments

Comments
 (0)