Leetcode203.移除链表元素
从此题开始我们接触到链表这一新的数据结构,注意链表的定义,基础内容不做过多描述
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
关键词:虚节点
题目思路:首先设置虚节点保证头节点的操作与后续节点相同,然后通过遍历链表解决问题,注意p节点的更新操作与目标节点的删除操作是并列关系,要考虑到删除后的节点依旧是目标节点的情况
![](https://img-blog.csdnimg.cn/img_convert/a935e36f9692a6552a747cf5df62bac6.png)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode *p = nullptr;
p = dummyHead;
while (p != nullptr && p->next != nullptr) {
if (p->next->val == val) {
ListNode *pre = p->next;
p->next = p->next->next;
delete pre;
}
else {
p = p->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
反思:注意new函数的理解与使用
Leetcode707.设计链表
该题是一些链表基础功的体现,注意虚节点的使用
处理问题的难点是如何判断索引是否有效,同时我们以索引作为循环终止的条件
在对链表进行遍历时类比数组的操作,不过是稍微繁琐一些
class MyLinkedList {
public:
struct ListNode {
int val;
ListNode *next;
ListNode(int val):val(val), next(nullptr){}
};
MyLinkedList() {
_dummyHead = new ListNode(0);
_size = 0;
}
int get(int index) {
if (index < 0 || index > _size - 1) return -1;
int result = 0;
ListNode *cur = _dummyHead;
while (index >= 0) {
cur = cur->next;
result = cur->val;
index--;
}
return result;
}
void addAtHead(int val) {
ListNode *cur = new ListNode(val);
cur->next = _dummyHead->next;
_dummyHead->next = cur;
_size++;
}
void addAtTail(int val) {
ListNode *p = new ListNode(val);
ListNode *cur = _dummyHead;
while (cur != nullptr && cur->next != nullptr) {
cur = cur->next;
}
cur->next = p;
_size++;
}
void addAtIndex(int index, int val) {
if (index > _size) return;
else {
if (index == _size) {
ListNode *cur = _dummyHead;
while (cur != nullptr && cur->next != nullptr) {
cur = cur->next;
}
ListNode *p = new ListNode(val);
cur->next = p;
_size++;
return;
}
if (index <= 0) {
ListNode *p = new ListNode(val);
p->next = _dummyHead->next;
_dummyHead->next = p;
_size++;
return;
}
}
ListNode *p = new ListNode(val);
ListNode *cur = _dummyHead;
while (index > 0) {
cur = cur->next;
index--;
}
p->next = cur->next;
cur->next = p;
_size++;
}
void deleteAtIndex(int index) {
if (index < 0 || index > _size - 1) return;
ListNode *cur = _dummyHead;
while (index > 0) {
cur = cur->next;
index--;
}
ListNode *p = cur->next;
cur->next = cur->next->next;
delete p;
_size--;
}
private:
ListNode *_dummyHead;
int _size;
};
反思:对于c++语言本身不够了解,需要加强学习相关语法知识,类的基本操作
Leetcode206.反转链表
关键词:递归
题目思路:借助这道题目理解递归函数的使用,使用关键是抽象函数的功能而忽略函数的实现细节,把函数理解为一个组件,不过我们是在未完成函数细节的情况下便将其作为一个组件使用,用于减小问题规模直到答案显而易见
比如此题,反转链表可以转化为反转以head->next为头节点的链表后把原head变为反转后链表的尾节点,注意我们反转链表之后(以示例1为例)head->next->val = 2这一点并未发生变化,故而有了我们的答案
![](https://img-blog.csdnimg.cn/img_convert/1be3f86b26960d0ff6379a9397025dba.png)
注意此处时间复杂度的分析,递归函数时间复杂度=递归次数*单次函数时间复杂度
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == nullptr || head->next == nullptr) return head;
ListNode *newHead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
}
};
反思:递归函数代码形式简洁,但是理解难度大,效率一般
今日学习时间:2.5h