持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
19. 删除链表的倒数第 N 个结点
思路
(双指针) O(n)
具体过程如下:
1、创建虚拟头节点dummy,并让dummy->next = head。
2、创建快指针first和慢指针second,并让其都指向dummy。
3、先让快指针first走n + 1步,而后first,second指针同时向后走,直到first指针指向空节点,此时second 指向节点的下一个节点就是需要删除的节点,将其删除。
4、最后返回虚拟头节点的下一个节点。
解释:
始终保持两个指针之间间隔 n 个节点,在 first 到达终点时,second 的下一个结点就是倒数第 n个节点。
时间复杂度分析: 只遍历一次链表,因此时间复杂度为O(n)。
c++代码
/**
* 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* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* first = dummy;
ListNode* second = dummy;
for(int i = 0; i <= n; i++) first = first->next;
while(first){
first = first->next;
second = second->next;
}
second->next = second->next->next;
return dummy->next;
}
};
20. 有效的括号
思路
(栈) O(n)
定义一个栈,从前往后枚举每个字符:
-
1、当遇到
'(','{','['左括号时,将元素压进栈中 -
2、当遇到
')',']','}'右括号时,- 如果栈不为空并且栈顶元素是对应的左括号,说明这是匹配的符号,将栈顶元素
pop出即可。 - 否则,表示不匹配,
return false。
- 如果栈不为空并且栈顶元素是对应的左括号,说明这是匹配的符号,将栈顶元素
-
3、最后,若栈是空栈,表示所有字符都已经匹配好了,若不是空栈,表示还存在未能匹配好的子符
时间复杂度分析: 每个字符最多进栈出栈一次,因此时间复杂度为O(n)。
c++代码
class Solution {
public:
bool isValid(string s) {
stack<int> stk;
for(int i = 0; i < s.size(); i++){
if(s[i] == '(' || s[i] == '{' || s[i] == '[') stk.push(s[i]);
else if(s[i] == ')'){
if(!stk.empty() && stk.top() == '(') stk.pop();
else return false;
}
else if(s[i] == '}'){
if(!stk.empty() && stk.top() == '{') stk.pop();
else return false;
}
else if(s[i] == ']'){
if(!stk.empty() && stk.top() == '[') stk.pop();
else return false;
}
}
return stk.empty();
}
};
21. 合并两个有序链表
思路
(线性合并) O(n)
解题过程如下:
-
新建虚拟头节点
dummy,定义cur指针并使其指向dummy。 -
当
l1或l2都不为为空时:- 若
l1->val < l2->val,则令cur的next指针指向l1且l1后移; - 若
l1->val >=l2->val,则令cur的next指针指向l2且l2后移; cur后移一步;
- 若
-
将剩余的
l1或l2接到cur指针后边。 -
最后返回
dummy->next。
时间复杂度分析: O(n)
c++代码
/**
* 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* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(-1);
ListNode* cur = dummy;
while(l1 && l2){
if(l1->val < l2->val){
cur->next = l1;
l1 = l1->next;
}else{
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
if(l1) cur->next = l1;
if(l2) cur->next = l2;
return dummy->next;
}
};