1. 反转链表
链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
这道链表题目已经做了很多遍,每次再遇到的时候还是会写出来小问题,我做这道题目用的整体思路是双指针法,本质的思路是存下来上一个节点以及下一个节点,依次把指针转过来即可,这次写题目的时候有一处错误需要注意:
知道存储上一节点以及下一节点,但是在第一次写的时候忘记更新cur指针,即一直都指向第一个节点,这样就进入了死循环,要注意更新节点。
详细代码如下:
/**
* 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 *pre = NULL;
ListNode* cur = head;
while(cur!=nullptr)
{
ListNode* tmp = cur->next;
cur->next=pre;
pre = cur;
cur=tmp;
}
return pre;
}
};
在看了代码随想录之后,学习了递归方法,了解到递归法其实和上述的双指针法是同一个思想,但是自己没想到这种方法,学习并记录一下:
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);
}
};
2. 移除链表元素
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
这道题目的关键就是为了避免头节点的值是val值写法比较麻烦这种情况,添加一个虚拟节点,这样头节点就会和后面节点是一样的,代码相对比较清晰。整体思路就是运用两个指针,pre指向当前节点的前一节点,cur指向当前节点,当cur的值等于val时,将pre指向cur->next,注意此时pre无需更新,因为下一节点仍然可能是相等;而在cur不等于时候,pre和cur同时更新即可。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* pre = dummy;
ListNode* cur = head;
while(cur)
{
if(cur->val==val)
{
ListNode* tmp = cur->next;
pre->next = tmp;
cur->next = nullptr;//为了更加严谨
cur=tmp;
}
else
{
pre = cur;
cur= cur->next;
}
}
return dummy->next;
}
};
(自己写的思路和随想录不一样,后续可以再看看随想录的算法)
3. 设计链表
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
这道题目主要卡在两个地方:1. 不知道怎么初始化链表,2.不知道怎么确认链表的长度。看了代码随想录之后学习到了解决方法:
1. 首先写一个结构体ListNode,里面代表链表的两个属性,然后再自定义类中初始化一个虚拟头节点,可以方便后续函数的操作;
struct ListNode
{
int val;
ListNode* next;
ListNode(int val):val(val),next(nullptr){}
};
MyLinkedList() {
_dummy = new ListNode(0);
_size = 0;
}
2. 可以在自定义类中增加一个私有变量_size代表链表的尺寸,这样就能知道链表的长度,但是需要注意在增加和删除数据时,需要维护这个_size变量
class MyLinkedList {
public:
struct ListNode
{
int val;
ListNode* next;
ListNode(int val):val(val),next(nullptr){}
};
MyLinkedList() {
_dummy = new ListNode(0);
_size = 0;
}
int get(int index) {
if(index>=_size) return -1;
ListNode* tmp = _dummy;
for(int i=0;i<=index;i++)
{
tmp = tmp->next;
}
return tmp->val;
}
void addAtHead(int val) {
ListNode* first = new ListNode(val);
ListNode* tmp = _dummy->next;
first->next = tmp;
_dummy->next = first;
_size++;
return;
}
void addAtTail(int val) {
ListNode* cur = _dummy;
for(int i=0;i<_size;i++)
{
cur=cur->next;
}
cur->next = new ListNode(val);
_size++;
}
void addAtIndex(int index, int val) {
if(index>_size) return;
ListNode* cur = _dummy;
int i=0;
while(i<index)
{
cur=cur->next;
i++;
}
ListNode* tmp = cur->next;
ListNode* node = new ListNode(val);
cur->next=node;
node->next = tmp;
_size++;
return;
}
void deleteAtIndex(int index) {
if(index>=_size) return;
ListNode* cur = _dummy;
for(int i=0;i<index;i++)
{
cur=cur->next;
}
cur->next = cur->next->next;
_size--;
return;
}
private:
int _size;
ListNode* _dummy;
};
/**
* 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);
*/
今日学习时长:两个半小时