Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add weekly contest 410 #3401

Merged
merged 2 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion solution/1000-1099/1035.Uncrossed Lines/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ tags:
<pre>
<strong>输入:</strong>nums1 = <span id="example-input-1-1">[1,4,2]</span>, nums2 = <span id="example-input-1-2">[1,2,4]</span>
<strong>输出:</strong><span id="example-output-1">2</span>
<strong>解释:</strong>可以画出两条不交叉的线,如上图所示。
<strong>解释:</strong>可以画出两条不交叉的线,如上图所示。
但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。
</pre>

Expand Down
293 changes: 293 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/README.md

Large diffs are not rendered by default.

291 changes: 291 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/README_EN.md

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Solution {
public:
int finalPositionOfSnake(int n, vector<string>& commands) {
int x = 0, y = 0;
for (const auto& c : commands) {
switch (c[0]) {
case 'U': x--; break;
case 'D': x++; break;
case 'L': y--; break;
case 'R': y++; break;
}
}
return x * n + y;
}
};
16 changes: 16 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/Solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
func finalPositionOfSnake(n int, commands []string) int {
x, y := 0, 0
for _, c := range commands {
switch c[0] {
case 'U':
x--
case 'D':
x++
case 'L':
y--
case 'R':
y++
}
}
return x*n + y
}
14 changes: 14 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/Solution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Solution {
public int finalPositionOfSnake(int n, List<String> commands) {
int x = 0, y = 0;
for (var c : commands) {
switch (c.charAt(0)) {
case 'U' -> x--;
case 'D' -> x++;
case 'L' -> y--;
case 'R' -> y++;
}
}
return x * n + y;
}
}
14 changes: 14 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/Solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Solution:
def finalPositionOfSnake(self, n: int, commands: List[str]) -> int:
x = y = 0
for c in commands:
match c[0]:
case "U":
x -= 1
case "D":
x += 1
case "L":
y -= 1
case "R":
y += 1
return x * n + y
10 changes: 10 additions & 0 deletions solution/3200-3299/3248.Snake in Matrix/Solution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function finalPositionOfSnake(n: number, commands: string[]): number {
let [x, y] = [0, 0];
for (const c of commands) {
c[0] === 'U' && x--;
c[0] === 'D' && x++;
c[0] === 'L' && y--;
c[0] === 'R' && y++;
}
return x * n + y;
}
274 changes: 274 additions & 0 deletions solution/3200-3299/3249.Count the Number of Good Nodes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
---
comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README.md
---

<!-- problem:start -->

# [3249. 统计好节点的数目](https://leetcode.cn/problems/count-the-number-of-good-nodes)

[English Version](/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/README_EN.md)

## 题目描述

<!-- description:start -->

<p>现有一棵 <strong>无向</strong> 树,树中包含 <code>n</code> 个节点,按从 <code>0</code> 到 <code>n - 1</code> 标记。树的根节点是节点 <code>0</code> 。给你一个长度为 <code>n - 1</code> 的二维整数数组 <code>edges</code>,其中 <code>edges[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> 表示树中节点 <code>a<sub>i</sub></code> 与节点 <code>b<sub>i</sub></code> 之间存在一条边。</p>

<p>如果一个节点的所有子节点为根的&nbsp;<span data-keyword="subtree">子树</span>&nbsp;包含的节点数相同,则认为该节点是一个 <strong>好节点</strong>。</p>

<p>返回给定树中<strong> 好节点 </strong>的数量。</p>

<p><strong>子树</strong>&nbsp;指的是一个节点以及它所有后代节点构成的一棵树。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><strong class="example">示例 1:</strong></p>

<div class="example-block">
<p><strong>输入:</strong><span class="example-io">edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]]</span></p>

<p><strong>输出:</strong><span class="example-io">7</span></p>

<p><strong>说明:</strong></p>
<img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/images/tree1.png" style="width: 360px; height: 158px;" />
<p>树的所有节点都是好节点。</p>
</div>

<p><strong class="example">示例 2:</strong></p>

<div class="example-block">
<p><strong>输入:</strong><span class="example-io">edges = [[0,1],[1,2],[2,3],[3,4],[0,5],[1,6],[2,7],[3,8]]</span></p>

<p><strong>输出:</strong><span class="example-io">6</span></p>

<p><strong>说明:</strong></p>
<img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/images/screenshot-2024-06-03-193552.png" style="width: 360px; height: 303px;" />
<p>树中有 6 个好节点。上图中已将这些节点着色。</p>
</div>

<p><strong class="example">示例 3:</strong></p>

<div class="example-block">
<p><span class="example-io"><b>输入:</b>edges = [[0,1],[1,2],[1,3],[1,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[9,12],[10,11]]</span></p>

<p><span class="example-io"><b>输出:</b>12</span></p>

<p><strong>解释:</strong></p>
<img alt="" src="https://fastly.jsdelivr.net/gh/doocs/leetcode@main/solution/3200-3299/3249.Count%20the%20Number%20of%20Good%20Nodes/images/rob.jpg" style="width: 450px; height: 277px;" />
<p>除了节点 9 以外其他所有节点都是好节点。</p>
</div>

<p>&nbsp;</p>

<p><strong>提示:</strong></p>

<ul>
<li><code>2 &lt;= n &lt;= 10<sup>5</sup></code></li>
<li><code>edges.length == n - 1</code></li>
<li><code>edges[i].length == 2</code></li>
<li><code>0 &lt;= a<sub>i</sub>, b<sub>i</sub> &lt; n</code></li>
<li>输入确保 <code>edges</code> 总表示一棵有效的树。</li>
</ul>

<!-- description:end -->

## 解法

<!-- solution:start -->

### 方法一:DFS

我们先根据题目给定的边 $\textit{edges}$ 构建出树的邻接表 $\textit{g}$,其中 $\textit{g}[a]$ 表示节点 $a$ 的所有邻居节点。

然后,我们设计一个函数 $\textit{dfs}(a, \textit{fa})$,表示计算以节点 $a$ 为根的子树中的节点数,并累计好节点的数量。其中 $\textit{fa}$ 表示节点 $a$ 的父节点。

函数 $\textit{dfs}(a, \textit{fa})$ 的执行过程如下:

1. 初始化变量 $\textit{pre} = -1$, $\textit{cnt} = 1$, $\textit{ok} = 1$,分别表示节点 $a$ 的某个子树的节点数、节点 $a$ 的所有子树的节点数、以及节点 $a$ 是否为好节点。
2. 遍历节点 $a$ 的所有邻居节点 $b$,如果 $b$ 不等于 $\textit{fa}$,则递归调用 $\textit{dfs}(b, a)$,返回值为 $\textit{cur}$,并累加到 $\textit{cnt}$ 中。如果 $\textit{pre} < 0$,则将 $\textit{cur}$ 赋值给 $\textit{pre}$;否则,如果 $\textit{pre}$ 不等于 $\textit{cur}$,说明节点 $a$ 的不同子树的节点数不同,将 $\textit{ok}$ 置为 $0$。
3. 最后,累加 $\textit{ok}$ 到答案中,并返回 $\textit{cnt}$。

在主函数中,我们调用 $\textit{dfs}(0, -1)$,最后返回答案。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 表示节点的数量。

<!-- tabs:start -->

#### Python3

```python
class Solution:
def countGoodNodes(self, edges: List[List[int]]) -> int:
def dfs(a: int, fa: int) -> int:
pre = -1
cnt = ok = 1
for b in g[a]:
if b != fa:
cur = dfs(b, a)
cnt += cur
if pre < 0:
pre = cur
elif pre != cur:
ok = 0
nonlocal ans
ans += ok
return cnt

g = defaultdict(list)
for a, b in edges:
g[a].append(b)
g[b].append(a)
ans = 0
dfs(0, -1)
return ans
```

#### Java

```java
class Solution {
private int ans;
private List<Integer>[] g;

public int countGoodNodes(int[][] edges) {
int n = edges.length + 1;
g = new List[n];
Arrays.setAll(g, k -> new ArrayList<>());
for (var e : edges) {
int a = e[0], b = e[1];
g[a].add(b);
g[b].add(a);
}
dfs(0, -1);
return ans;
}

private int dfs(int a, int fa) {
int pre = -1, cnt = 1, ok = 1;
for (int b : g[a]) {
if (b != fa) {
int cur = dfs(b, a);
cnt += cur;
if (pre < 0) {
pre = cur;
} else if (pre != cur) {
ok = 0;
}
}
}
ans += ok;
return cnt;
}
}
```

#### C++

```cpp
class Solution {
public:
int countGoodNodes(vector<vector<int>>& edges) {
int n = edges.size() + 1;
vector<int> g[n];
for (const auto& e : edges) {
int a = e[0], b = e[1];
g[a].push_back(b);
g[b].push_back(a);
}
int ans = 0;
auto dfs = [&](auto&& dfs, int a, int fa) -> int {
int pre = -1, cnt = 1, ok = 1;
for (int b : g[a]) {
if (b != fa) {
int cur = dfs(dfs, b, a);
cnt += cur;
if (pre < 0) {
pre = cur;
} else if (pre != cur) {
ok = 0;
}
}
}
ans += ok;
return cnt;
};
dfs(dfs, 0, -1);
return ans;
}
};
```

#### Go

```go
func countGoodNodes(edges [][]int) (ans int) {
n := len(edges) + 1
g := make([][]int, n)
for _, e := range edges {
a, b := e[0], e[1]
g[a] = append(g[a], b)
g[b] = append(g[b], a)
}
var dfs func(int, int) int
dfs = func(a, fa int) int {
pre, cnt, ok := -1, 1, 1
for _, b := range g[a] {
if b != fa {
cur := dfs(b, a)
cnt += cur
if pre < 0 {
pre = cur
} else if pre != cur {
ok = 0
}
}
}
ans += ok
return cnt
}
dfs(0, -1)
return
}
```

#### TypeScript

```ts
function countGoodNodes(edges: number[][]): number {
const n = edges.length + 1;
const g: number[][] = Array.from({ length: n }, () => []);
for (const [a, b] of edges) {
g[a].push(b);
g[b].push(a);
}
let ans = 0;
const dfs = (a: number, fa: number): number => {
let [pre, cnt, ok] = [-1, 1, 1];
for (const b of g[a]) {
if (b !== fa) {
const cur = dfs(b, a);
cnt += cur;
if (pre < 0) {
pre = cur;
} else if (pre !== cur) {
ok = 0;
}
}
}
ans += ok;
return cnt;
};
dfs(0, -1);
return ans;
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- problem:end -->
Loading
Loading