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.
1#include <stdio.h>
2#include <stdlib.h>
3
4struct Node {
5 int val;
6 struct Node* next;
7};
8
9struct MyLinkedList {
10 struct Node* head;
11};
12
13struct MyLinkedList* myLinkedListCreate() {
14 struct MyLinkedList* obj = (struct MyLinkedList*)malloc(sizeof(struct MyLinkedList));
15 obj->head = NULL;
16 return obj;
17}
18
19void myLinkedListAddAtHead(struct MyLinkedList* obj, int val) {
20 struct Node* node = (struct Node*)malloc(sizeof(struct Node));
21 node->val = val;
22 node->next = obj->head;
23 obj->head = node;
24}
25
26void myLinkedListAddAtTail(struct MyLinkedList* obj, int val) {
27 struct Node* node = (struct Node*)malloc(sizeof(struct Node));
28 node->val = val;
29 node->next = NULL;
30 if (obj->head == NULL) {
31 obj->head = node;
32 } else {
33 struct Node* current = obj->head;
34 while (current->next != NULL) {
35 current = current->next;
36 }
37 current->next = node;
38 }
39}
40
41int myLinkedListGet(struct MyLinkedList* obj, int index) {
42 struct Node* current = obj->head;
43 int i = 0;
44 while (current != NULL && i < index) {
45 current = current->next;
46 i++;
47 }
48 return (current == NULL) ? -1 : current->val;
49}
50
51void myLinkedListAddAtIndex(struct MyLinkedList* obj, int index, int val) {
52 if(index == 0) {
53 myLinkedListAddAtHead(obj, val);
54 return;
55 }
56 struct Node* current = obj->head;
57 for(int i = 0; current != NULL && i < index - 1; i++) {
58 current = current->next;
59 }
60 if (current == NULL) return;
61 struct Node* node = (struct Node*)malloc(sizeof(struct Node));
62 node->val = val;
63 node->next = current->next;
64 current->next = node;
65}
66
67void myLinkedListDeleteAtIndex(struct MyLinkedList* obj, int index) {
68 struct Node* current = obj->head;
69 if (index == 0 && current != NULL) {
70 obj->head = current->next;
71 free(current);
72 return;
73 }
74 struct Node* prev = NULL;
75 for (int i = 0; current != NULL && i < index; i++) {
76 prev = current;
77 current = current->next;
78 }
79 if(current == NULL) return;
80 prev->next = current->next;
81 free(current);
82}
83
84void myLinkedListFree(struct MyLinkedList* obj) {
85 struct Node* current = obj->head;
86 while (current != NULL) {
87 struct Node* next = current->next;
88 free(current);
89 current = next;
90 }
91 free(obj);
92}
The above code implements a singly linked list in C. It provides functions to add nodes at the head, tail, a specific index, get the value at an index, and delete a node at an index. The linked list maintains a head pointer and nodes are dynamically allocated using malloc
.
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.
1
class MyLinkedList {
private:
struct Node {
int val;
Node* next;
Node* prev;
Node(int _val) : val(_val), next(nullptr), prev(nullptr) {}
};
Node* head;
public:
MyLinkedList() : head(nullptr) {}
int get(int index) {
Node* current = head;
for (int i = 0; current && i < index; ++i) {
current = current->next;
}
return current ? current->val : -1;
}
void addAtHead(int val) {
Node* node = new Node(val);
node->next = head;
if (head) head->prev = node;
head = node;
}
void addAtTail(int val) {
Node* node = new Node(val);
if (!head) {
head = node;
} else {
Node* current = head;
while (current->next) {
current = current->next;
}
current->next = node;
node->prev = current;
}
}
void addAtIndex(int index, int val) {
if (index == 0) {
addAtHead(val);
return;
}
Node* current = head;
for (int i = 0; current && i < index - 1; ++i) {
current = current->next;
}
if (current) {
Node* node = new Node(val);
node->next = current->next;
if (current->next) current->next->prev = node;
current->next = node;
node->prev = current;
}
}
void deleteAtIndex(int index) {
Node* current = head;
for (int i = 0; current && i < index; ++i) {
current = current->next;
}
if (!current) return;
if (current->prev) current->prev->next = current->next;
else head = current->next;
if (current->next) current->next->prev = current->prev;
delete current;
}
};
This C++ solution introduces a doubly linked list node structure with pointers to both previous and next nodes, allowing operations like insertion and deletion from either end or the middle more efficiently than singly linked lists.