代码随想录算法训练营第三天 | 203.移除链表元素,707.设计链表,206.反转链表
)
203.移除链表元素
题目链接
具体实现(C++):
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *H = new ListNode(-1, head);
ListNode *p = H;
while(p->next!=nullptr ){
if(p->next->val == val){
ListNode * tmp = p->next;
p->next = p->next->next;
delete tmp;
}
else{
p = p->next;
}
}
head = H->next;
delete H;
return head;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
707.设计链表
题目链接
具体实现(C++):
class MyLinkedList {
public:
struct LinkNode{
int val;
LinkNode * next;
LinkNode(int x): val(x),next(nullptr){}
};
// 初始化链表
MyLinkedList() {
_dummyHead = new LinkNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
_size = 0;
}
int get(int index) {
if (index > (_size - 1) || index < 0) {
return -1;
}
LinkNode * cur = _dummyHead->next;
while(index-- > 0){
cur = cur->next;
}
return cur->val;
}
// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
void addAtHead(int val) {
LinkNode* newNode = new LinkNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
// 在链表最后面添加一个节点
void addAtTail(int val) {
LinkNode* newNode = new LinkNode(val);
LinkNode* cur = _dummyHead;
while(cur->next != nullptr){
cur = cur->next;
}
cur->next = newNode;
_size++;
}
// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果index大于链表的长度,则返回空
// 如果index小于0,则在头部插入节点
void addAtIndex(int index, int val) {
// if(index > _size || index < 0){ //注意增加和查找与删除的索引范围不一样,可以在链表的后一个位置插入
// return ;
// }
if(index > _size) return;
if(index < 0) index = 0;
LinkNode * n = new LinkNode(val);
LinkNode * cur = _dummyHead;
while(index--){
cur = cur->next;
}
n->next = cur->next;
cur->next = n;
_size++; //好的,我又忘了!
}
void deleteAtIndex(int index) {
if(index > _size-1 || index < 0){
return ;
}
LinkNode * cur = _dummyHead;
while(index-- ){
cur = cur->next;
}
LinkNode *tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
tmp=nullptr; //记得delete掉并给tmp符空指针,避免后续程序使用tmp指向随机空间
_size--;
}
private:
int _size;
LinkNode* _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);
*/
时间复杂度: 涉及 index 的相关操作为 O(index), 其余为 O(1)
空间复杂度: O(n)
206.反转链表
题目链接
具体实现(C++):
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode * first = nullptr;
ListNode * second = head;
// if(second == nullptr|| second->next == nullptr ){
// return second;
// }
while(second != nullptr){
ListNode * tmp = second;
second = second->next;
tmp->next = first;
first = tmp;
}
return first;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
总结
- 学会定义单链表、注意释放内存
- 学会定义一个数据结构(勉强算是吧),对于一个数据结构在修改元素时注意维护其size值,增加时可考虑的位置与删、查时不一样
- 多动手、稍微长一点的代码漏洞百出
- 熟悉了反转链表的流程(动图记住了),要分割好每次循环的固定操作。