系列文章目录
【代码随想录】Day3 链表1,● 203.移除链表元素 ● 707.设计链表 ● 206.反转链表
前言
Day3 链表1
203.移除链表元素
Source: 203.移除链表元素
Note:相当简单的一道题,考察dummy结点的使用,注意c++中p!=NULL的判定条件
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy = new ListNode(-1);
ListNode* p = head;
ListNode* pre = dummy;
dummy->next = head;
while (p!= NULL){
if (p->val == val) {
pre->next = p->next;
p = p->next;
}else{
p = p->next;
pre = pre->next;
}
}
return dummy->next;
}
};
707.设计链表
Source: 707.设计链表
Note:设计并完成链表的各种操作,题目难度在于对于各种基础操作需要熟练掌握
//注意这里的结构,如果使用ListNode会和原有的冲突,初始化使用list
struct NewListNode {
int val;
NewListNode* next;
NewListNode(int val) : val(val), next(nullptr){};
};
//初始化
MyLinkedList() {
//伪头节点
dummy = new NewListNode(0);
//使用size的原因是调用get时候方便判断
size = 0;
}
//链表的头插 尾插 索引插 索引删 读取 用单个指针就够了
class MyLinkedList {
public:
struct NewListNode {
int val;
NewListNode* next;
NewListNode(int val) : val(val), next(nullptr){};
};
//初始化
MyLinkedList() {
//伪头节点
dummy = new NewListNode(0);
//使用size的原因是调用get时候方便判断
size = 0;
}
int get(int index) {
if (index > size - 1 || index < 0) {
return -1;
}
NewListNode* cur = dummy->next;
while (index--) {
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
NewListNode* newNode = new NewListNode(val);
newNode->next = dummy->next;
dummy->next = newNode;
size++;
}
void addAtTail(int val) {
NewListNode* cur = dummy;
while (cur->next != NULL) {
cur = cur->next;
}
cur->next = new NewListNode(val);
size++;
}
void addAtIndex(int index, int val) {
if (index > size || index < 0) {
return ;
}
NewListNode* cur = dummy;
while (index--){
cur = cur->next;
}
NewListNode* newNode = new NewListNode(val);
NewListNode* tmp = cur->next;
cur->next = newNode;
cur->next->next = tmp;
size++;
}
void deleteAtIndex(int index) {
if (index > size - 1 || index < 0) {
return ;
}
NewListNode* cur = dummy;
while (index--){
cur = cur->next;
}
cur->next = cur->next->next;
size--;
}
//添加成员变量 方便对链表进行操作
private:
int size;
NewListNode* dummy;
};
C++运行31ms 击败96%
206.反转链表
Source: 206.反转链表
如何对整个链表进行翻转?双指针(**重要)或者递归
递归比较抽象
双指针法:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
// 这道题不需要dummy节点 因为需要prev初始化为null来进行翻转
ListNode* prev = NULL;
ListNode* cur = head;
// 需要好好思考指针的操作先后顺序
// 停止条件是cur移动到null,此时正好prev移动到原链表最后一位(新链表的头部),故跳出循环
while (cur!= NULL) {
ListNode* tmp = cur->next;
cur->next = prev;
prev = cur;
cur = tmp;
}
return prev;
}
};
递归法:
class Solution {
public:
ListNode* reverse(ListNode* cur,ListNode* prev){
// 结束递归的条件是 cur指向null,此时prev指向原链表最后一位,与上面的方法一样
if (cur == NULL) {
return prev;
}
// 仔细看下面几行,发现和双指针法的核心是一样的,都使用tmp保存cur的下一个节点
ListNode* tmp = cur->next;
cur->next = prev;
ListNode* head = reverse(tmp, cur);
return head;
}
ListNode* reverseList(ListNode* head) {
return reverse(head, NULL);
}
};
总结
今天主要详细理解了链表的基本操作 双指针在链表的用法(以及递归)
DAY3 Finished 撒花~