您现在的位置是:首页 >技术教程 >LeetCode 1042. Flower Planting With No Adjacent【模拟,图,BFS,DFS】中等网站首页技术教程
LeetCode 1042. Flower Planting With No Adjacent【模拟,图,BFS,DFS】中等
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。
为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。
由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。
You have n
gardens, labeled from 1
to n
, and an array paths
where paths[i] = [xi, yi]
describes a bidirectional path between garden xi
to garden yi
. In each garden, you want to plant one of 4 types of flowers.
All gardens have at most 3 paths coming into or leaving it.
Your task is to choose a flower type for each garden such that, for any two gardens connected by a path, they have different types of flowers.
Return any such a choice as an array answer
, where answer[i]
is the type of flower planted in the (i+1)th
garden. The flower types are denoted 1
, 2
, 3
, or 4
. It is guaranteed an answer exists.
Example 1:
Input: n = 3, paths = [[1,2],[2,3],[3,1]]
Output: [1,2,3]
Explanation:
Gardens 1 and 2 have different types.
Gardens 2 and 3 have different types.
Gardens 3 and 1 have different types.
Hence, [1,2,3] is a valid answer. Other valid answers include [1,2,4], [1,4,2], and [3,2,1].
Example 2:
Input: n = 4, paths = [[1,2],[3,4]]
Output: [1,2,1,2]
Example 3:
Input: n = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]]
Output: [1,2,3,4]
Constraints:
1 <= n <= 10^4
0 <= paths.length <= 2 * 10^4
paths[i].length == 2
1 <= xi, yi <= n
xi != yi
- Every garden has at most 3 paths coming into or leaving it.
题意:有 n
个花园,按从 1
到 n
标记。另有数组 paths
,其中 paths[i] = [xi, yi]
描述了花园 xi
到花园 yi
的双向路径。在每个花园中,你打算种下四种花之一。另外,所有花园 最多 有 3 条路径可以进入或离开。需要为每个花园选择一种花,使得通过路径相连的任何两个花园中的花的种类互不相同。
以数组形式返回 任一 可行的方案作为答案 answer
,其中 answer[i]
为在第 (i+1)
个花园中种植的花的种类。花的种类用 1、2、3、4 表示。保证存在答案。
解法 模拟+暴力
出题人可能是受到四色定理的启发出的题。问题相当于用 4 4 4 种颜色给图中的每个节点染色,要求相邻节点颜色不同。而「所有花园最多有 3 3 3 条路径可以进入或离开」,这相当于图中每个点的度数至多为 3 3 3 ,那么只要选一个和邻居不同的颜色即可。
哈希表(数组)实现:
class Solution {
public:
vector<int> gardenNoAdj(int n, vector<vector<int>>& paths) {
vector<vector<int>> g(n);
vector<int> ans(n);
for (vector<int> &v : paths) {
g[v[0] - 1].push_back(v[1] - 1); // 从0开始
g[v[1] - 1].push_back(v[0] - 1);
}
for (int i = 0; i < n; ++i) { // 给结点i选择颜色
bool used[5]{};
for (int j: g[i]) used[ans[j]] = true;
while (used[++ans[i]]) ;
}
return ans;
}
};
位运算实现: 我们需要找到 u s e d used used 从低到高第一个 0 0 0 的位置,即第一个未使用的颜色,这需要我们计算 u s e d used used 取反后的尾零个数。例如 used = 1011 1 ( 2 ) extit{used}=10111_{(2)} used=10111(2) ,取反后变为 100 0 ( 2 ) 1000_{(2)} 1000(2) (实际前导零也取反了,但不影响计算),尾零个数为 3 3 3 ,这恰好就是从低位到高位第一个 0 0 0 的位置。
class Solution {
public:
vector<int> gardenNoAdj(int n, vector<vector<int>>& paths) {
vector<vector<int>> g(n);
vector<int> ans(n);
for (vector<int> &v : paths) {
g[v[0] - 1].push_back(v[1] - 1); // 从0开始
g[v[1] - 1].push_back(v[0] - 1);
}
for (int i = 0; i < n; ++i) { // 给结点i选择颜色
int used = 1; // 由于颜色是1~4,把0加入mask保证下面不会算出0
for (int j: g[i]) used |= 1 << ans[j];
ans[i] = __builtin_ctz(~used);
}
return ans;
}
};
复杂度分析:
- 时间复杂度: O ( n + m ) O(n+m) O(n+m) ,其中 m m m 为 p a t h s paths paths 的长度。
- 空间复杂度: O ( n + m ) O(n+m) O(n+m) 。