难度: 中等
题目大意:
给你一个链表的头节点
head
。移除每个右侧有一个更大数值的节点。
返回修改后链表的头节点
head
。
输入:head = [5,2,13,3,8]
输出:[13,8]
解释:需要移除的节点是 5 ,2 和 3 。
- 节点 13 在节点 5 右侧。
- 节点 13 在节点 2 右侧。
- 节点 8 在节点 3 右侧。
我们可以从右往左边考虑,维护一个最大值mx
,如果递归到当前节点的值大于mx
,那么更新最大值,同时更新指向
class Solution {
public:
ListNode* removeNodes(ListNode* head) {
ListNode* res(0);
int mx = 0;
function<void(ListNode*)> dfs = [&](ListNode* u) -> void {
if (!u) return;
dfs(u->next);
if (u->val >= mx) {
mx = u->val;
ListNode* t = new ListNode(mx);
t->next = res;
res = t;
}
};
dfs(head);
return res;
}
};
时间复杂度: O ( n ) O(n) O(n)
我们仔细分析题目可以发现,根据单调栈的实现过程,留下来的这些节点不就是单调栈剩余的节点吗。所以就有了下面的代码实现
class Solution {
public:
ListNode* removeNodes(ListNode* head) {
stack<ListNode*> stk;
while (head) {
while (stk.size() && stk.top()->val < head->val) stk.pop();
stk.push(head);
head = head->next;
}
ListNode* t(0), *res;
res = stk.top(); stk.pop();
while (stk.size()){
t = stk.top(); stk.pop();
t->next = res;
res = t;
}
return res;
}
};
时间复杂度 O ( n ) O(n) O(n)
结束了