目录
一、链表基础操作
203.移除链表元素
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* newHead = new ListNode();
newHead->next = head;
ListNode* p = newHead;
while (p->next != NULL)
{
if (p->next->val == val) {
//删除链表记得释放空间
ListNode* temp = p->next;
p->next = p->next->next;
delete temp;
}
else {
p = p->next;
}
}
head = newHead->next;
//释放虚拟头节点
delete newHead;
return head;
}
};
本题对于打好链表基础非常重要,尤其是最开始链表的定义。其包括数值、next指针(仍为链表类型)和构造函数。
本体采用了虚拟头节点方法保持了删除链表第一个元素时的操作与删除其它元素的操作一致。须注意一下几点:
1.删除元素记得释放空间;
2.返回head指针要让head=newHead->next;
3.记得释放虚拟头节点的空间。
707.设计链表
class MyLinkedList {
public:
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) {}
};
MyLinkedList() {
//虚拟头节点
this->m_Head = new ListNode();
this->m_Size = 0;
}
int get(int index) {
if (index < 0 || index >= this->m_Size) {
return -1;
}
ListNode* p = this->m_Head;
for (int i = 0; i <= index; i++) {
p = p->next;
}
int res = p->val;
return res;
}
void addAtHead(int val) {
ListNode* elem = new ListNode(val);
elem->next = this->m_Head->next;
this->m_Head->next = elem;
this->m_Size++;
}
void addAtTail(int val) {
ListNode* elem = new ListNode(val);
ListNode* p = this->m_Head;
while (p->next != NULL) {
p = p->next;
}
p->next = elem;
this->m_Size++;
}
void addAtIndex(int index, int val) {
if (index > this->m_Size) {
return;
}
else if (index <= 0) {
addAtHead(val);
this->m_Size++;
}
else {
ListNode* elem = new ListNode(val);
ListNode* p = this->m_Head;
for (int i = 0; i < index; i++) {
p = p->next;
}
elem->next = p->next;
p->next = elem;
this->m_Size++;
}
}
void deleteAtIndex(int index) {
if (index >= 0 && index < this->m_Size) {
ListNode* p = this->m_Head;
while (index--) {
p = p->next;
}
ListNode* temp = p->next;
p->next = temp->next;
delete temp;
this->m_Size--;
}
else {
return;
}
}
~MyLinkedList() {
if (this->m_Head != NULL) {
delete this->m_Head;
this->m_Head = NULL;
}
}
private:
ListNode* m_Head;
int m_Size;
};
都是链表的基础操作,添加和删除不要忘记修改size属性。
二、双指针法
206.反转链表
class MyLinkedList {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* temp = NULL;
while (cur != NULL) {
//保存下一个节点
temp = cur->next;
//进行翻转
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};
用两个指针完成反转,过程参考上图(来源:代码随想录)。初始cur指向头节点,pre指向NULL。利用temp保存下一个节点的信息后,完成当前两个节点的反转。