11. 合并两个有序链表
/**
* 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) {
auto dummy = new ListNode(-1);
auto cur = dummy;
while (l1 && l2) {
if (l1->val <= l2->val) {
cur->next = l1;
cur = cur->next;
l1 = l1->next;
}
else {
cur->next = l2;
cur = cur->next;
l2 = l2->next;
}
}
while (l1) {
cur->next = l1;
l1 = l1->next;
cur = cur->next;
}
while (l2) {
cur->next = l2;
l2 = l2->next;
cur = cur->next;
}
return dummy->next;
}
};
12. 括号生成
class Solution {
public:
vector<string> res;
vector<string> generateParenthesis(int n) {
dfs(n, 0, 0, "");
return res;
}
void dfs(int n, int lc, int rc, string seq) {
if (lc == n && rc == n) res.push_back(seq);
else {
if (lc < n) dfs(n, lc + 1, rc, seq + '(');
if (rc < n && rc < lc) dfs(n, lc, rc + 1, seq + ')');
}
}
};
13. 合并k个升序链表
思路
使用优先队列保存每一个链表头结点,重载比较函数,比较顺序为值从小到大排列,每一次取出队头元素加入新的队列中,如果链表还没有结束,加入链表后一个元素队列中,直到优先队列为空
/**
* 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:
struct Cmp {
bool operator() (ListNode* a, ListNode* b) {
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, Cmp> heap;
auto dummy = new ListNode(-1), tail = dummy;
for (auto& l : lists) {
if (l) heap.push(l);
}
while (heap.size()) {
auto t = heap.top();
heap.pop();
tail = tail->next = t;
if (t->next) heap.push(t->next);
}
return dummy->next;
}
};
14. 下一个排列
思路
从末尾找第一个非降序的元素,交换后段第一个大于其元素,再对后段翻转
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int k = nums.size() - 1;
while (k && nums[k - 1] >= nums[k]) k -- ;
if (k == 0) reverse(nums.begin(), nums.end());
else {
int t = k;
while (t < nums.size() && nums[t] > nums[k - 1]) t ++ ;
swap(nums[k - 1], nums[t - 1]);
reverse(nums.begin() + k, nums.end());
}
}
};
15. 最长有效括号
思路(较复杂,代码很简单)
分段的思想,每一段合法括号序列分开的,找出分界点,每一次碰到左括号入栈,右括号出栈,判断栈中剩余括号,如果还有,作为某一段括号合法序列的端点,如果没有剩余,从上一个端点开始到这个右括号之间都是合法的;如果右括号入栈时,栈为空,说明右括号的数量多了,右括号作为合法括号序列端点前一个点
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> stk;
int res = 0;
for (int i = 0, start = -1; i < s.size(); i ++ ) {
if (s[i] == '(') stk.push(i);
else {
if (stk.size()) {
stk.pop();
if (stk.size()) {
res = max(res, i - stk.top());
}
else res = max(res, i - start);
}
else {
start = i;
}
}
}
return res;
}
};