前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是五月集训第十二天:链表
一、练习题目
1290. 二进制链表转整数
237. 删除链表中的节点
剑指 Offer II 024. 反转链表
1019. 链表中的下一个更大节点
二、算法思路
- 1、1290. 二进制链表转整数:遍历链表节点,进行一点数学运算。
- 2、237. 删除链表中的节点:如果我们需要删除当前节点,只需要将前驱节点的后继指针指向当前节点的后继指针。但这需要我们能访问到前驱节点,在不是双链表的前提下我们并不能直接做到这一点。所以这里的trick就是;我们并不是真的删除当前节点,删除的仍然是当前节点的后继;但是我们把当前节点伪装成下一个节点。看图就很清楚了;标星的位置是目标节点。我们没法在物理上删除它,所以我们把后继节点的值覆写到当前节点,就从红色节点变成了绿色节点;但他的地址没有变化,这是和双链表删除当前节点不一样的本质。然后我们把后继节点删除;删除方式就是把当前节点的后继指针指向后继的后继即可。这就是一整个偷梁换柱了。图微扰酱大佬的传送门。
- 3、剑指 Offer II 024. 反转链表:用的头插法,我把每一步代码画成了图,不过我不太会画图,记录下来以后自己忘了也方便回忆。
* 4、1019. 链表中的下一个更大节点:维护一个单调递减栈。
三、源码分析
// 1290. 二进制链表转整数
class Solution {
public:
int getDecimalValue(ListNode* head) {
int ans = 0;
while(head) {
ans = (ans << 1) | head->val; //(1)
head = head->next;
}
return ans;
}
};
- 1、位运算求和。
// 237. 删除链表中的节点
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}
};
- 1、看思路分析的图吧
// 剑指 Offer II 024. 反转链表
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == nullptr) {
return nullptr;
}
ListNode* dummyhead = new ListNode();
dummyhead->next = head;
ListNode *pre = head, *now = head->next;
while(now) {
//删除now,插到虚拟头结点处
pre->next = now->next;
now->next = dummyhead->next;
dummyhead->next = now;
// 更新now
now = pre->next;
}
return dummyhead->next;
}
};
- 1、看图。
// 1019. 链表中的下一个更大节点
class Solution {
public:
vector<int> nextLargerNodes(ListNode* head) {
stack<pair<int, int> > stk;
vector<int> ans;
int index = 0;
for(int i = 0; i < 10000; ++i) {
ans.push_back(0);
}
while(head) {
while(!stk.empty() && head->val > stk.top().second) {
int idx = stk.top().first;
ans[idx] = head->val;
stk.pop();
}
stk.push(pair{index, head->val});
index++;
head = head->next;
}
while(ans.size() > index) {
ans.pop_back();
}
return ans;
}
};
- 1、看图
四、总结
今天的题目适合画图来理清思路,花了一点时间画图。