目录
203.移除链表元素
文档:代码随想录
视频:B站视频
链表操作有两种方式:
1、直接使用原来的链表来进行删除操作
因为单链表的特殊性,只能指向下一个节点,如果删除的是头结点呢?
移除头结点和移除其他节点的操作不一样,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。只要将头结点向后移动一位,就从链表中移除了一个头结点。
这样移在单链表中移除头结点 和 移除其他节点的操作方式是不一样,在写代码的时候也需要单独写一段逻辑来处理移除头结点的情况。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//删除头结点
while(head !=NULL && head->val == val)
{
ListNode* temp = head;
head = head->next;
delete temp;
}
//删除非头结点
ListNode* cur = head;
while(cur != NULL && cur->next != NULL)
{
if(cur->next->val == val)
{
ListNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
}
else
{
cur = cur->next;
}
}
return head;
}
};
那么可不可以 以一种统一的逻辑来移除 链表的节点呢。
其实可以设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。
2、设置一个虚拟头结点在进行删除操作
这给链表添加一个虚拟头结点为新的头结点,就可以使用和移除链表其他节点的方式统一了呢?
来看一下,如何移除元素1 呢,还是熟悉的方式,然后从内存中删除元素1。
最后呢在题目中,return 头结点的时候,别忘了 return dummyNode->next;
, 这才是新的头结点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next != NULL)
{
if(cur->next->val == val)
{
ListNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
}
else
{
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
707.设计链表
题目:Leetcode设计链表
文档:代码随想录
视频:B站视频
沿用虚拟头结点方法:
class MyLinkedList {
public:
//定义单链表结构体
struct LinkedNode
{
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){}
};
//初始化链表
MyLinkedList()
{
dummyHead = new LinkedNode(0);
size = 0;
}
//获取链表中下标为index的节点的值。如果下标无效,则返回-1
int get(int index) {
if(index >(size -1) || index < 0)
{
return -1;
}
LinkedNode* cur = dummyHead->next;
while(index--)
{
cur = cur->next;
}
return cur->val;
}
//将一个值为 val 的节点插入到链表中第一个元素之前
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);
newNode->next = dummyHead->next;
dummyHead->next = newNode;
size++;
}
//将一个值为 val 的节点追加到链表中作为链表的最后一个元素
void addAtTail(int val) {
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = dummyHead;
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = newNode;
size++;
}
//将一个值为 val 的节点插入到链表中下标为 index 的节点之前
void addAtIndex(int index, int val) {
if(index > size)
return;
if(index < 0)
index = 0;
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = dummyHead;
while(index--)
{
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
size++;
}
//如果下标有效,则删除链表中下标为 index 的节点
void deleteAtIndex(int index) {
if(index >= size || index < 0)
return;
LinkedNode* cur = dummyHead;
while(index--)
cur = cur->next;
LinkedNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
temp = nullptr;
size--;
}
private:
int size;
LinkedNode* dummyHead;
};
206.反转链表
题目:Leetcode反转链表
文档:代码随想录
视频:B站视频
改变链表的next指针的指向,直接将链表反转
首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
然后开始反转,首先把 cur->next 节点用temp指针保存,以便反转后还能找到cur->next
接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。
最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点
1、双指针法:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* temp;
ListNode* cur = head;
ListNode* pre = NUll;
while(cur)
{
temp = cur->next;
cur ->next =pre;
pre = cur;
cur = temp;
}
return pre;
}
};
2、递归法:
class Solution {
public:
ListNode* reverse(ListNode* pre,ListNode* cur) {
if(cur == NULL)
return pre;
ListNode* temp = cur->next;
cur->next = pre;
return reverse(cur, temp);
}
ListNode* reverseList (ListNode* head){
return reverse(NULL, head);
}
};