LeetCode第270场周赛
T1 5942. 找出 3 位偶数
题目描述:
给你一些数字,找出所有使用其中任意三个数字组成的不含前导\(0\)的偶数。
思路:
考虑到数字个数很少,直接暴力三重循环然后用\(map\)判重并统计答案即可,注意最后要对答案数组进行排序。
时间复杂度:\(O(n^3)\)
参考代码:
class Solution {
public:
vector<int> findEvenNumbers(vector<int>& digits) {
vector<int> res;
map<int, int>mp;
int n = digits.size();
for(int i = 0 ; i < n ; ++i)
for(int j = 0 ; j < n ; ++j)
for(int k = 0 ; k < n ; ++k){
if(i == j || i == k || j == k) continue;
if(digits[i] == 0) continue;
int dx = digits[i] * 100 + digits[j] * 10 + digits[k];
if(dx & 1) continue;
if(mp.count(dx)) continue;
res.push_back(dx);
mp[dx] = 1;
}
sort(res.begin(), res.end());
return res;
}
};
T2 5943. 删除链表的中间节点
题目描述:
删除链表的中间节点,中间节点的定义为位于链表\(\llcorner \frac{n}{2} \lrcorner\)处的节点(\(n\)为链表节点的数量)
思路:
先统计出链表节点的数量,然后根据题意删除即可
时间复杂度:\(O(n)\)
参考代码:
class Solution {
public:
ListNode* deleteMiddle(ListNode* head) {
int cnt = 0;
ListNode* p = head;
while(p != nullptr){
++cnt;
p = p->next;
}
if(cnt == 1) return nullptr;
cnt >>= 1;
cnt--;
p = head;
while(cnt > 0){
--cnt;
p = p->next;
}
p->next = p->next->next;
return head;
}
};
T3 5944. 从二叉树一个节点到另一个节点每一步的方向
题目描述:
给你一个二叉树,每个节点有一个\(val\),节点的\(val\)两两不同,然后给你起点和终点,让你输出从起点到终点的行走方式
思路:
考虑第一遍\(dfs\)将每个节点的父结点预处理出来,然后第二遍\(dfs\)将起点所对应的节点找到,第三遍\(dfs\)以起点为根进行搜索求解,注意过程中标记访问和进行答案的记录
时间复杂度:\(O(n)\)
参考代码:
class Solution {
private:
void dfs(TreeNode* root , TreeNode* father , vector<TreeNode*>& fa){
if(root == nullptr) return ;
fa[root->val] = father;
dfs(root->left , root , fa);
dfs(root->right , root , fa);
return ;
}
TreeNode* dfs1(TreeNode* root , int val){
if(root == nullptr) return nullptr;
if(root->val == val) return root;
TreeNode* left = dfs1(root->left , val);
if(left != nullptr) return left;
return dfs1(root->right , val);
}
string res;
bool flag;
void dfs(TreeNode* root , int val, vector<int>& vis , vector<TreeNode*>& fa){
if(root == nullptr || vis[root->val]) return ;
if(root->val == val) flag = true;
if(flag) return ;
vis[root->val] = 1;
res += 'L';
dfs(root->left , val, vis , fa);
if(flag) return ;
res.pop_back();
res += 'R';
dfs(root->right , val , vis , fa);
if(flag) return ;
res.pop_back();
res += 'U';
dfs(fa[root->val], val , vis , fa);
if(flag) return ;
res.pop_back();
return ;
}
public:
string getDirections(TreeNode* root, int startValue, int destValue) {
vector<TreeNode*> fa = vector<TreeNode*>(100005 , nullptr);
vector<int> vis = vector<int>(100005 , 0);
dfs(root , nullptr , fa);
TreeNode* start = dfs1(root , startValue);
dfs(start , destValue , vis , fa);
return res;
}
};
T4 5932. 合法重新排列数对
题目描述:
给你\(n\)个二元组\([start , end]\),让你重新排列这些二元组使得对于任意的\(1 \leq i < n\),满足\(end_{i - 1} = start_i\)
思路:
比较明显的求欧拉路径的题目。由于二元组中的值比较大,所以先进行离散化处理,然后建立相应的单向边,由于题目保证有解,所以我们在建好图后,根据欧拉路径的判定定理,以及这题是单向边,所以找到入度-出度为\(1\)(如果存在)的点或者任选一个点(前一种点不存在)作为起点,然后进行\(dfs\)并记录相应的路径即可,最后将路径倒置并转换成相应的二元组即为所求。注意到求解过程中需要删除边,所以使用multiset存图。
时间复杂度: \(O(nlogn)\)
参考代码:
class Solution {
private:
void dfs(vector<multiset<int>>& graph, int u, vector<int>& path) {
for (auto v = graph[u].begin(); v != graph[u].end(); v = graph[u].begin()) {
int val = *v;
graph[u].erase(v);
dfs(graph, val, path);
}
path.push_back(u);
}
public:
vector<vector<int>> validArrangement(vector<vector<int>>& pairs) {
vector<int>a;
for (auto p : pairs) a.push_back(p[0]), a.push_back(p[1]);
sort(a.begin(), a.end());
int tot = unique(a.begin(), a.end()) - a.begin();
unordered_map<int, int> mp;
int idx = 0;
for (int i = 0; i < tot; ++i) mp[a[i]] = ++idx;
int n = tot + 5;
vector<multiset<int>>graph(n + 1);
vector<int> income(n + 1, 0);
vector<int> outcome(n + 1, 0);
for (auto p : pairs) {
graph[mp[p[0]]].insert(mp[p[1]]);
outcome[mp[p[0]]]++;
income[mp[p[1]]]++;
}
int start = 1;
for (int i = 1; i <= idx; ++i)
if (outcome[i] - income[i] == 1) {
start = i;
break;
}
vector<int>path;
dfs(graph, start, path);
reverse(path.begin(), path.end());
vector<vector<int>> res;
int m = path.size();
for (int i = 0; i < m - 1; ++i) {
res.push_back({ a[path[i] - 1] , a[path[i + 1] - 1] });
}
return res;
}
};
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。