题目描述
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性: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
。
解题思路
1.定义了一个名为LinkedNode的结构体,用于表示链表节点,结构体包含节点的值val和指向下一个节点的指针next。
2.MyLinkedList类中使用了一个名为_dummyHead的虚拟头节点,这样可以避免处理头节点的特殊情况,并将链表的初始大小_size初始化为0。
3.实现了get方法用于获取指定位置节点的值,addAtHead方法用于在链表头部插入节点,addAtTail方法用于在链表尾部插入节点,addAtIndex方法用于在指定位置插入节点,deleteAtIndex方法用于删除指定位置的节点。
4. 需要注意的是,在addAtTail方法中,通过遍历寻找尾部节点之后再进行插入操作,而在deleteAtIndex方法中,首先遍历找到要删除节点的前一个节点,然后进行节点删除操作。 这样的设计和实现满足了题目的要求,能够有效地对链表进行操作,并且使用了一个虚拟头节点来简化边界情况的处理。
算法实现
C++实现
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode*next;
LinkedNode(int val):val(val),next(nullptr){}
};
MyLinkedList() {
_dummyHead=new LinkedNode(0);
_size=0;
}
int get(int index) {
if(index<0||index>_size-1)
{
return -1;
}
LinkedNode*cur=_dummyHead->next;
while(index--)
{
cur=cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode*newNode=new LinkedNode(val);
newNode->next=_dummyHead->next;
_dummyHead->next=newNode;
_size++;
}
void addAtTail(int val) {
//int n=_size;
LinkedNode*newNode=new LinkedNode(val);
LinkedNode*cur=_dummyHead;
while(cur->next!=NULL)
{
cur=cur->next;
}
newNode->next=cur->next;
cur->next=newNode;
_size++;
}
void addAtIndex(int index, int val) {
if(index<0) index=0;
if(index>_size) return;
LinkedNode*newNode=new LinkedNode(val);
LinkedNode*cur=_dummyHead;
while(index--)
{
cur=cur->next;
}
newNode->next=cur->next;
cur->next=newNode;
_size++;
}
void deleteAtIndex(int index) {
if(index<0||index>_size-1)
{
return;
}
LinkedNode*cur=_dummyHead;
while(index--)
{
cur=cur->next;
}
LinkedNode*tmp=cur->next;
cur->next=cur->next->next;
delete tmp;
tmp=nullptr;
_size--;
}
private:
int _size;
LinkedNode*_dummyHead;
};
/**
* 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);
*/
复杂度分析
- 时间复杂度:在get、addAtHead、addAtTail、addAtIndex和deleteAtIndex操作中,时间复杂度均为O(n),其中n为链表的长度。
- 空间复杂度:空间复杂度也为O(n),主要是链表节点的空间占用。
总结
通过以上实现,我们设计并实现了一个简单的单链表MyLinkedList类,实现了初始化链表、获取指定位置节点值、在头部、尾部和指定位置插入节点,以及删除指定位置的节点等功能。这个实现是基于C++的,可以满足LeetCode707题目的要求。
希望这篇博客能对你有所帮助,如果有任何问题,欢迎和我一起讨论。
标签:index,cur,val,707,next,链表,节点,LeetCode From: https://blog.csdn.net/J_z_Yang/article/details/143063575