移除链表中的元素&设计链表&反转链表
207. 移除链表中的元素
力扣链接:https://leetcode.cn/problems/remove-linked-list-elements/submissions/
题目描述:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
/**
* 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* L = new ListNode();
L->next = head;
ListNode* p = head;
ListNode* pre = L;
while (p) {
if (p->val == val) {
pre->next = p->next;
p = p->next;
} else {
pre = p;
p = p->next;
}
}
return L->next;
}
};
-
对于链表的删除建议使用带有头结点的方式,题目中
head
指针是指向链表的第一个元素,并不是“头结点” -
首先创建一个结点作为头结点:
ListNode* L = new ListNode();
-
单链表删除操作建议:
p
指针作为遍历指针pre
指向p结点 -
在C++中单链表的结构体的定义:
// 单链表 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) {} // 节点的构造函数 };
707. 设计链表
力扣链接:https://leetcode.cn/problems/design-linked-list/submissions/
题目描述:
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val
和 next
。val
是当前节点的值,next
是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev
以指示链表中的上一个节点。假设链表中的所有节点都是 0-index
的。
在链表类中实现这些功能:
get(index)
:获取链表中第 index 个节点的值。如果索引无效,则返回-1。
addAtHead(val)
:在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
addAtTail(val)
:将值为 val 的节点追加到链表的最后一个元素。
addAtIndex(index,val)
:在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
deleteAtIndex(index)
:如果索引 index 有效,则删除链表中的第 index 个节点。
题解:
class MyLinkedList {
public:
struct ListNode {
int val;
ListNode* next;
ListNode() :val(0), next(nullptr) {}
ListNode(int val) :val(val), next(nullptr) {}
};
MyLinkedList() {
_dummyHead = new ListNode();
_size = 0;
}
int get(int index) {
if (index < 0 || index > _size - 1) {
return -1;
}
ListNode* p = _dummyHead->next;
while (index--) {
p = p->next;
}
return p->val;
}
void addAtHead(int val) {
ListNode* newNode = new ListNode(val);
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
_size++;
}
void addAtTail(int val) {
ListNode* newNode = new ListNode(val);
ListNode* p = _dummyHead;
while (p->next != nullptr) {
p = p->next;
}
p->next = newNode;
_size++;
}
void addAtIndex(int index, int val) {
if (index == _size) {
addAtTail(val);
return;
} else if (index < 0) {
addAtHead(val);
return;
} else if (index > _size) {
return;
}
ListNode* newNode = new ListNode(val);
ListNode* pre = _dummyHead;
while (index--) {
pre = pre->next;
}
newNode->next = pre->next;
pre->next = newNode;
_size++;
}
void deleteAtIndex(int index) {
if (index < 0 || index > _size - 1) {
return;
}
ListNode* pre = _dummyHead;
while (index--) {
pre = pre->next;
}
pre->next = pre->next->next;
_size--;
}
private:
int _size; // 链表中元素个数
ListNode* _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);
*/
收获与总结
- C++设计链表使用:全局变量使用private关键字修饰,一把使用下划线_标识
- 题目中要求
0-index
说明下标是从0开始,即第0个元素,第一个元素…
206. 反转链表
力扣链接:https://leetcode.cn/problems/reverse-linked-list/
题目描述:
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
解法1:头插法进行链表的翻转
/**
* 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* L = new ListNode(); // 虚拟头结点
ListNode* p = head;
while (p != nullptr) {
head = head->next;
p->next = L->next;
L->next = p;
p = head;
}
return L->next;
}
};
- 反转链表可以使用头插法进行链表的翻转:新建一个虚拟头结点
p
是变量指针,head
作用是保存链表当前结点之后的链表指针,防止断链 - 每遍历到一个结点,使用头插法将p结点插入L中
解法2:递归的方式链表的翻转
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur) {
if (cur == nullptr) return pre;
ListNode* tmp = cur->next;
cur->next = pre;
return reverse(cur, tmp);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr, head);
}
};
递归函数设计:
- 递归出口:参数
cur = nullptr
- tmp指针是保存链表的后续结点,防止断链
- cur进行反向,
cur->next = pre