203. 移除链表元素
题目(著作权归领扣网络所有)
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
提示: 列表中的节点数目在范围 [0, 104] 内 1 <= Node.val <= 50 0 <= val <= 50
思路
为了方便实现删除操作,定义一个虚拟头结点。然后从头开始向后遍历,定义一个cur指针,指向待删除结点的前面一个结点,若符合条件的结点则进行删除。
代码
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) {}
}*List, Node;//Cpp中可以这么给结构体起个名字
void DeleteNode(ListNode* q, ListNode* pre){
// 一般情况 删除结点前后都有结点
pre->next = q->next;
free(q);
}
ListNode* removeElements(ListNode* head, int val)
{
ListNode* p = head;
while(p->next != NULL)
{
if(p->next->val == val){
DeleteNode(p->next, p);
//删除该结点 定义一个删除结点函数
}
else
p = p->next;
}
return head;
}
707. 设计链表
思路
设计链表这一题要实现多个操作,包括查询元素、删除元素以及增加元素。其中,在删除或者增加一个结点时,结点的个数要进行变化。
代码
class MyLinkedList{
public:
struct LinkNode{
int val;
LinkNode* next;
LinkNode(int val): val(val), next(nullptr){}
};
//问:CPP中类如何初始化?
//初始化链表
MyLinkedList(){
_dummyHead = new LinkNode(0);
//问:_size变量有什么作用?
_size = 0;
}
int get(int index){
if (index > _size - 1 || index < 0 ){
return -1;
}
// else{
// LinkNode* cur = _dummyHead->next;
// while(index--){
// cur = cur->next;
// }
// return cur->val;
// }
//代码优化
LinkNode* cur = _dummyHead->next;
while(index--){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val){
LinkNode* tmp = new LinkNode(val);
tmp->next = _dummyHead->next;
_dummyHead->next = tmp;
_size++;//这个量要记得变化
}
void addAtTail(int val){
LinkNode* newNode = new LinkNode(val);
// if(_size == 0){
// newNode->next = _dummyHead->next;
// _dummyHead->next = newNode;
// }
// else{
// LinkNode* cur = _dummyHead;
// while(cur->next != nullptr){
// cur = cur->next;
// }
// newNode->next = cur->next;
// cur->next = newNode;
// }
//代码优化
LinkNode* cur = _dummyHead;
while(cur->next != nullptr){
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;//链表大小要加一
}
void addAtIndex(int index, int val) {
if (index > _size) {
return ;
}
LinkNode* newNode = new LinkNode(val);
if(index < 0){
newNode->next = _dummyHead->next;
_dummyHead->next = newNode;
return;
}
LinkNode* cur = _dummyHead;
while(index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
void deleteIndex(int index){
if(index >= _size || index < 0){//要注意对数据有效性的判断
return;
}
LinkNode* cur = _dummyHead;
while(index--){
cur = cur->next;
}
LinkNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;//CPP中别忘了要释放结点
_size--;//别忘了链表结点数减一
}
void printLinkedList(){
LinkNode* cur = _dummyHead->next;
while(cur != nullptr){
printf("%d ", cur->val);//换种写法 cout << cur->val << " ";
cur = cur->next;
}
printf("\n");//cout << endl;
}
private:
int _size;
LinkNode* _dummyHead;
};
206. 反转链表
题目
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
链表中节点的数目范围是 [0, 5000] -5000 <= Node.val <= 5000
思路
定义两个指针pre、cur,分别指向前面的结点和当前结点,依次实现反转。
递归版本
LinkNode* reverseList(LinkNode* &head) {
//递归实现
LinkNode* oldHead = head;
head = reverse(nullptr, head->next);
oldHead->next = head;
head = oldHead;
return head;
}
LinkNode* reverse(LinkNode* pre, LinkNode* cur){
if(cur == nullptr)
return pre;
LinkNode* tmp =cur->next;
cur->next = pre;
pre = reverse(cur, tmp);
return pre;
}
非递归版本
LinkNode* reverseList(LinkNode* &head) {
if(head->next == nullptr)
return head;
LinkNode* cur = head->next;
head->next = nullptr;
while (cur != nullptr){
LinkNode* tmp = cur->next;
cur->next = head->next;
head->next = cur;
cur = tmp;
}
return head->next;
}