day 3 移除链表元素 反转链表 设计链表 增删改查
文章目录
移除链表元素
Problem: 203. 移除链表元素
思路
链表是一个老生常谈的数据结构了,从大一就开始写链表,但是一直傻傻分不清头结点和头指针,王道和408的考题均是头结点,但是力扣一般是头指针,话句话说就是升学考试一般是头结点,就业工作是头指针。头指针和头结点刚开始是不一样的,但是carl的方法,虚拟头结点,可以将头指针转换为头结点来做,十分方便!
解题方法
删除要判断的应该是p->next
还有一个要注意的点是删除以后,不要让指针移动;
不删除的时候,才能让指针p = p->next;因为你删掉以后,由于判断的是next,已经是新的了,所以不需要移动,如果移动了那么会跳过这个新的。
Code
/**
* 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 *vir = new ListNode(0);
vir->next = head;
ListNode *p = vir;
while(p->next)
{
if(p->next->val == val)
{
ListNode *tmp = p->next;
p->next = tmp->next;
delete(tmp);
}
else{
p = p->next;
}
}
head = vir->next;
delete(vir);
return head;
}
};
反转链表
Problem: 206. 反转链表
思路
反转链表的第二种,直接通过pr和p去翻转。
解题方法
注意点:保留下一跳的节点,
temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
可以对比出来:假如场景是 1–>2–>3
第一步,保存3节点,是让temp到3保证3的存在;
第二步,让p去指向1;
第三步,移动pr;
第四步,移动p
双指针要移动两步,然后翻转next一步,保存结点一步,一共四步。
反转链表和交换链表两个结点还是不一样的。反转链表可以看成头删和往一个NULL的链表中头插
这里写成了pre有些不好理解,其实可以把pre看成一个新的链表。
Code
/**
* 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 *pr = NULL;
ListNode *p = head;
while(p)
{
ListNode *tmp = p->next;
p->next = p->pre;
pre = p;
p = temp;
}
head = pr;
return head;
}
};
反转链表 头插头删
Problem: 206. 反转链表
思路
链表的翻转:头删和头插
解题方法
问题在于只有一份实际存在的节点,如果想让节点改变新的顺序到新的链表,那么必定保持不了原来的链表的顺序。所以一定要一个删一个插,而不是一个遍历一个插
Code
/**
* 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 *pNew = new ListNode(0);
ListNode *p = new ListNode(0);
p->next = head;
while(p->next)
{
ListNode *tmp = p->next;
p->next = tmp->next;
tmp->next = pNew->next;
pNew->next = tmp;
}
return pNew->next;
}
};
设计链表 增删改查
Problem: 707. 设计链表
思路
摒弃头指针的方法,头结点好简单。
解题方法
入参判断有些麻烦,不过问题不大。
Code
class MyLinkedList {
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
public:
MyLinkedList() {
vir = new LinkedNode(0);
size= 0;
}
int get(int index) {
if(index < 0 || index > (size-1))
{
return -1;
}
LinkedNode *p = vir;
while(index)
{
p = p->next;
index--;
}
return p->next->val;
}
void addAtHead(int val) {
LinkedNode *p = vir;
LinkedNode *pNew = new LinkedNode(val);
pNew->next = vir->next;
vir->next = pNew;
size++;
}
void addAtTail(int val) {
LinkedNode *pNew = new LinkedNode(val);
LinkedNode *p = vir;
while(p->next)
{
p = p->next;
}
p->next = pNew;
size++;
}
void addAtIndex(int index, int val) {
if(index > size) return;
if(index < 0) index = 0;
LinkedNode *p = vir;
while(index)
{
p = p->next;
index--;
}
LinkedNode *pNew = new LinkedNode(val);
pNew->val = val;
pNew->next = p->next;
p->next = pNew;
size++;
}
void deleteAtIndex(int index) {
LinkedNode *p = vir;
if(index < 0 || index >= size)
{
return ;
}
while(index)
{
p = p->next;
index--;
}
LinkedNode *tmp = p->next;
p->next = p->next->next;
delete(tmp);
tmp = NULL;
size--;
}
private:
LinkedNode *vir;
int size;
};
/**
* 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);
*/