LeetCode 347 Top K Frequent Elements AND 22 Generate Parentheses
347 Top K Frequent Elements
题意
给一个非空整数数组,求出现次数最多的K个不同的数,题目保证k有效。要求时间复杂度优于O(nlogn)。
思路
本以为会有O(n)的方法,但思考不出来,看了讨论版之后发现点赞最多的使用的是unordered_map
+ 优先队列。unordered_map
实际上是采用哈希方法实现的map,区别于使用红黑树实现的map
,复杂度基本上为O(n)左右,而后在使用优先队列时候有一个小技巧:假设有n个不同的数,需要拿出K个值最大的,如果我们每次随机拿一个出来,那当我们拿出来n-k+1个数时,这n-k+1个数中最大的那个一定是要拿出的K个数中的一个。因此整体的复杂度为优先队列的O(n log(n - k)),因为优先队列(也就是大顶堆)最多包含n-k
个元素。
代码
class Solution {
public:
vector<int> topKFrequent(vector<int> &nums, int k) {
unordered_map<int, int> m;
for (auto &&tmp : nums) {
m[tmp]++;
}
vector<int> res;
priority_queue<pair<int, int>> q;
for (auto it = m.begin(); it != m.end(); it++) {
q.push(make_pair(it->second, it->first));
if (q.size() > m.size() - k) {
res.push_back(q.top().second);
q.pop();
}
}
return res;
}
};
22 Generate Parentheses
题意
给一个数n,表示n对小括号,写一个函数生成这n对括号的所有合法组合。
思路
如果回溯递归写的多的话这个难度其实不大,记录一下左括号和右括号分别有多少个,大概过程无非就是:
递归:
左右括号都用完了?
得到一个结果
返回
左括号还有?
加一个左括号
更新可用左括号,继续递归
当前的字符串里右括号比左括号少?
加一个右括号
更新可用右括号,继续递归
然后递归即可。需要注意的是括号的组合中,右括号是不能比左括号多的,也就是 已用的右括号 <= 已用的左括号
。
代码
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string s;
dfs(0, 0, n, "", res);
return res;
}
void dfs(int lbn, int rbn, int n, string s, vector<string> &res) {
if (lbn == n && lbn == rbn)
res.push_back(s);
if (lbn < n)
dfs(lbn + 1, rbn, n, s + "(", res);
if (rbn < lbn)
dfs(lbn, rbn + 1, n, s + ")", res);
}
};
总结
两个题目难度不是很大,关键看对递归,回溯以及map和优先队列这些数据结构的熟练程度了。