Sponsored
Sponsored
In this approach, you will design a singly linked list where each node has a value and a pointer to the next node. This type of list is simple and efficient for certain operations, especially when traversing only forwards is sufficient.
Time Complexity:
- get
: O(n)
- addAtHead
: O(1)
- addAtTail
: O(n)
- addAtIndex
: O(n)
- deleteAtIndex
: O(n)
Space Complexity: O(n), where n is the number of nodes in the list.
This Python solution uses a class-based approach to represent nodes and the singly linked list. The list starts at the head node and supports operations like adding and removing elements at various positions efficiently.
This approach designs a doubly linked list, allowing traversal both forwards and backwards. Each node maintains a reference to both the next and previous node, facilitating operations such as adding or removing nodes from either end more efficiently.
Time Complexity:
- get
: O(n)
- addAtHead
: O(1)
- addAtTail
: O(n)
- addAtIndex
: O(n)
- deleteAtIndex
: O(n)
Space Complexity: O(n), where n is the number of nodes in the list.
1class Node {
2 constructor(val) {
3 this.val = val;
4 this.next = null;
5 this.prev = null;
6 }
7}
8
9class MyLinkedList {
10 constructor() {
11 this.head = null;
12 }
13
14 get(index) {
15 let current = this.head;
16 for (let i = 0; i < index; i++) {
17 if (!current) return -1;
18 current = current.next;
19 }
20 return current ? current.val : -1;
21 }
22
23 addAtHead(val) {
24 const node = new Node(val);
25 node.next = this.head;
26 if (this.head) this.head.prev = node;
27 this.head = node;
28 }
29
30 addAtTail(val) {
31 const node = new Node(val);
32 if (!this.head) {
33 this.head = node;
34 return;
35 }
36 let current = this.head;
37 while (current.next) {
38 current = current.next;
39 }
40 current.next = node;
41 node.prev = current;
42 }
43
44 addAtIndex(index, val) {
45 if (index === 0) {
46 this.addAtHead(val);
47 return;
48 }
49 let current = this.head;
50 for (let i = 0; i < index - 1; i++) {
51 if (!current) return;
52 current = current.next;
53 }
54 if (current) {
55 const node = new Node(val);
56 node.next = current.next;
57 if (current.next) current.next.prev = node;
58 current.next = node;
59 node.prev = current;
60 }
61 }
62
63 deleteAtIndex(index) {
64 let current = this.head;
65 for (let i = 0; i < index && current; i++) {
66 current = current.next;
67 }
68 if (!current) return;
69 if (current.prev) current.prev.next = current.next;
70 else this.head = current.next;
71 if (current.next) current.next.prev = current.prev;
72 }
73}
The JavaScript solution modifies each node to hold previous pointers as well, ensuring operations such as insertion and deletion take advantage of bi-directional traversal to improve efficiency.
Solve with full IDE support and test cases