题目:
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev
以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList
类:
MyLinkedList()
初始化MyLinkedList
对象。int get(int index)
获取链表中下标为index
的节点的值。如果下标无效,则返回-1
。void addAtHead(int val)
将一个值为val
的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)
将一个值为val
的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)
将一个值为val
的节点插入到链表中下标为index
的节点之前。如果index
等于链表的长度,那么该节点会被追加到链表的末尾。如果index
比长度更大,该节点将 不会插入 到链表中。void deleteAtIndex(int index)
如果下标有效,则删除链表中下标为index
的节点。
示例:
输入 ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] [[], [1], [3], [1, 2], [1], [1], [1]] 输出 [null, null, null, null, 2, null, 3] 解释 MyLinkedList myLinkedList = new MyLinkedList(); myLinkedList.addAtHead(1); myLinkedList.addAtTail(3); myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 myLinkedList.get(1); // 返回 2 myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 myLinkedList.get(1); // 返回 3
提示:
0 <= index, val <= 1000
- 请不要使用内置的 LinkedList 库。
- 调用
get
、addAtHead
、addAtTail
、addAtIndex
和deleteAtIndex
的次数不超过2000
。
思路:
很简单的设计链表过程,主要是复习链表的C++语法。
这里使用单链表解题。
解题过程:
首先定义链表的结构体,以及构造函数。
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode() : val(0), next(nullptr) {}
LinkedNode(int val) : val(val), next(nullptr){}
LinkedNode(int x, LinkedNode *next) : val(x), next(next) {}
};
创建全局变量size与头节点指针head。
LinkedNode* head;
int size;
定义构造函数。
MyLinkedList() {
this->head = new LinkedNode();
this->size = 0;
}
实现get方法,简单遍历。
int get(int index) {
if(index > size || index < 0){
return -1;
}
LinkedNode* cur = head;
for(int i = 0; i <= index; i++){
cur = cur->next;
}
return cur->val;
}
实现头插方法。将新节点的next指针指向head->next,然后将head的next指针指向新节点。最后别忘了size++。
void addAtHead(int val) {
LinkedNode* n = new LinkedNode(val, head->next);
head->next = n;
size++;
}
实现尾插方法。遍历到链表末尾,将末尾节点的next指针指向新节点。最后别忘了size++。
void addAtTail(int val) {
LinkedNode* cur = head;
for(int i = 0; i < size; i++){
cur = cur->next;
}
LinkedNode* n = new LinkedNode(val);
cur->next = n;
size++;
}
实现按下标插入节点方法。使指针cur遍历到下标节点的前一个节点。新节点指向cur->next,cur->next指向新节点。size++。
void addAtIndex(int index, int val) {
LinkedNode* cur = head;
for(int i = 0; i < index; i++){
cur = cur->next;
}
LinkedNode* n = new LinkedNode(val, cur->next);
cur->next = n;
size++;
}
按下标删除节点。使指针cur指向下标节点的前一个节点。新建一个指针pre指向删除节点,将cur的next指针指向cur->next->next。删除pre指向的节点,释放指针指向的内存。最后别忘了size--;
void deleteAtIndex(int index) {
LinkedNode* cur = head;
for(int i = 0; i < index; i++){
cur = cur->next;
}
LinkedNode* pre = cur->next;
cur->next = cur->next->next;
delete pre;
pre=nullptr;
size--;
}
题解:
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode() : val(0), next(nullptr) {}
LinkedNode(int val) : val(val), next(nullptr){}
LinkedNode(int x, LinkedNode *next) : val(x), next(next) {}
};
LinkedNode* head = NULL;
int size = 0;
MyLinkedList() {
this->head = new LinkedNode();
this->size = 0;
}
int get(int index) {
if(index > size || index < 0){
return -1;
}
LinkedNode* cur = head;
for(int i = 0; i <= index; i++){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode* n = new LinkedNode(val, head->next);
head->next = n;
size++;
}
void addAtTail(int val) {
LinkedNode* cur = head;
for(int i = 0; i < size; i++){
cur = cur->next;
}
LinkedNode* n = new LinkedNode(val);
cur->next = n;
size++;
}
void addAtIndex(int index, int val) {
LinkedNode* cur = head;
for(int i = 0; i < index; i++){
cur = cur->next;
}
LinkedNode* n = new LinkedNode(val, cur->next);
cur->next = n;
size++;
}
void deleteAtIndex(int index) {
LinkedNode* cur = head;
for(int i = 0; i < index; i++){
cur = cur->next;
}
LinkedNode* pre = cur->next;
cur->next = cur->next->next;
delete pre;
pre=nullptr;
size--;
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/