Skip to content

Commit 59d6ac2

Browse files
authored
feat: add solutions to lc problem: No.2673 (doocs#2373)
No.2673.Make Costs of Paths Equal in a Binary Tree
1 parent 207245b commit 59d6ac2

File tree

7 files changed

+122
-167
lines changed

7 files changed

+122
-167
lines changed

solution/2600-2699/2673.Make Costs of Paths Equal in a Binary Tree/README.md

+45-56
Original file line numberDiff line numberDiff line change
@@ -62,47 +62,43 @@
6262

6363
## 解法
6464

65-
### 方法一
65+
### 方法一:贪心
66+
67+
根据题目描述,我们需要计算最小的增加次数,使得根节点到每个叶子节点的路径值相等。
68+
69+
根节点到每个叶子节点的路径值相等,实际上等价于以任意节点为根节点的子树到该子树的每个叶子节点的路径值相等。
70+
71+
为什么呢?我们可以用反证法来证明。假设存在一个节点 $x$,以它为根节点的子树到某个叶子节点的路径值不相等,那么也就存在着根节点到叶子节点的路径值不相等的情况,这与“根节点到每个叶子节点的路径值相等”矛盾。因此假设不成立,以任意节点为根节点的子树到该子树的每个叶子节点的路径值相等。
72+
73+
我们可以从树的底部开始,逐层向上计算增加次数。对于每个非叶子节点,我们可以计算它的左右孩子节点的路径值,增加的次数为两者路径值的差值,然后将左右孩子节点的路径值更新为两者中的较大值。
74+
75+
最后返回总的增加的次数即可。
76+
77+
时间复杂度 $O(n)$,其中 $n$ 为节点数。空间复杂度 $O(1)$。
6678

6779
<!-- tabs:start -->
6880

6981
```python
7082
class Solution:
7183
def minIncrements(self, n: int, cost: List[int]) -> int:
72-
def dfs(i: int) -> int:
73-
if (i << 1) > n:
74-
return cost[i - 1]
75-
l, r = dfs(i << 1), dfs(i << 1 | 1)
76-
nonlocal ans
77-
ans += max(l, r) - min(l, r)
78-
return cost[i - 1] + max(l, r)
79-
8084
ans = 0
81-
dfs(1)
85+
for i in range(n >> 1, 0, -1):
86+
l, r = i << 1, i << 1 | 1
87+
ans += abs(cost[l - 1] - cost[r - 1])
88+
cost[i - 1] += max(cost[l - 1], cost[r - 1])
8289
return ans
8390
```
8491

8592
```java
8693
class Solution {
87-
private int[] cost;
88-
private int n;
89-
private int ans;
90-
9194
public int minIncrements(int n, int[] cost) {
92-
this.n = n;
93-
this.cost = cost;
94-
dfs(1);
95-
return ans;
96-
}
97-
98-
private int dfs(int i) {
99-
if ((i << 1) > n) {
100-
return cost[i - 1];
95+
int ans = 0;
96+
for (int i = n >> 1; i > 0; --i) {
97+
int l = i << 1, r = i << 1 | 1;
98+
ans += Math.abs(cost[l - 1] - cost[r - 1]);
99+
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
101100
}
102-
int l = dfs(i << 1);
103-
int r = dfs(i << 1 | 1);
104-
ans += Math.max(l, r) - Math.min(l, r);
105-
return cost[i - 1] + Math.max(l, r);
101+
return ans;
106102
}
107103
}
108104
```
@@ -112,49 +108,42 @@ class Solution {
112108
public:
113109
int minIncrements(int n, vector<int>& cost) {
114110
int ans = 0;
115-
function<int(int)> dfs = [&](int i) -> int {
116-
if ((i << 1) > n) {
117-
return cost[i - 1];
118-
}
119-
int l = dfs(i << 1);
120-
int r = dfs(i << 1 | 1);
121-
ans += max(l, r) - min(l, r);
122-
return cost[i - 1] + max(l, r);
123-
};
124-
dfs(1);
111+
for (int i = n >> 1; i > 0; --i) {
112+
int l = i << 1, r = i << 1 | 1;
113+
ans += abs(cost[l - 1] - cost[r - 1]);
114+
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
115+
}
125116
return ans;
126117
}
127118
};
128119
```
129120
130121
```go
131122
func minIncrements(n int, cost []int) (ans int) {
132-
var dfs func(int) int
133-
dfs = func(i int) int {
134-
if (i << 1) > n {
135-
return cost[i-1]
136-
}
137-
l, r := dfs(i<<1), dfs(i<<1|1)
138-
ans += max(l, r) - min(l, r)
139-
return cost[i-1] + max(l, r)
123+
for i := n >> 1; i > 0; i-- {
124+
l, r := i<<1, i<<1|1
125+
ans += abs(cost[l-1] - cost[r-1])
126+
cost[i-1] += max(cost[l-1], cost[r-1])
140127
}
141-
dfs(1)
142-
return ans
128+
return
129+
}
130+
131+
func abs(x int) int {
132+
if x < 0 {
133+
return -x
134+
}
135+
return x
143136
}
144137
```
145138

146139
```ts
147140
function minIncrements(n: number, cost: number[]): number {
148141
let ans = 0;
149-
const dfs = (i: number): number => {
150-
if (i << 1 > n) {
151-
return cost[i - 1];
152-
}
153-
const [a, b] = [dfs(i << 1), dfs((i << 1) | 1)];
154-
ans += Math.max(a, b) - Math.min(a, b);
155-
return cost[i - 1] + Math.max(a, b);
156-
};
157-
dfs(1);
142+
for (let i = n >> 1; i; --i) {
143+
const [l, r] = [i << 1, (i << 1) | 1];
144+
ans += Math.abs(cost[l - 1] - cost[r - 1]);
145+
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
146+
}
158147
return ans;
159148
}
160149
```

solution/2600-2699/2673.Make Costs of Paths Equal in a Binary Tree/README_EN.md

+45-56
Original file line numberDiff line numberDiff line change
@@ -54,47 +54,43 @@ It can be shown that this is the minimum answer we can achieve.
5454

5555
## Solutions
5656

57-
### Solution 1
57+
### Solution 1: Greedy Algorithm
58+
59+
According to the problem description, we need to calculate the minimum number of increments to make the path values from the root node to each leaf node equal.
60+
61+
The path values from the root node to each leaf node being equal is actually equivalent to the path values from any node as the root of a subtree to each leaf node of that subtree being equal.
62+
63+
Why is that? We can prove it by contradiction. Suppose there is a node $x$, and the path values from it as the root of a subtree to some leaf nodes are not equal. Then there exists a situation where the path values from the root node to the leaf nodes are not equal, which contradicts the condition "the path values from the root node to each leaf node are equal". Therefore, the assumption is not valid, and the path values from any node as the root of a subtree to each leaf node of that subtree are equal.
64+
65+
We can start from the bottom of the tree and calculate the number of increments layer by layer. For each non-leaf node, we can calculate the path values of its left and right child nodes. The number of increments is the difference between the two path values, and then update the path values of the left and right child nodes to the larger one of the two.
66+
67+
Finally, return the total number of increments.
68+
69+
The time complexity is $O(n)$, where $n$ is the number of nodes. The space complexity is $O(1)$.
5870

5971
<!-- tabs:start -->
6072

6173
```python
6274
class Solution:
6375
def minIncrements(self, n: int, cost: List[int]) -> int:
64-
def dfs(i: int) -> int:
65-
if (i << 1) > n:
66-
return cost[i - 1]
67-
l, r = dfs(i << 1), dfs(i << 1 | 1)
68-
nonlocal ans
69-
ans += max(l, r) - min(l, r)
70-
return cost[i - 1] + max(l, r)
71-
7276
ans = 0
73-
dfs(1)
77+
for i in range(n >> 1, 0, -1):
78+
l, r = i << 1, i << 1 | 1
79+
ans += abs(cost[l - 1] - cost[r - 1])
80+
cost[i - 1] += max(cost[l - 1], cost[r - 1])
7481
return ans
7582
```
7683

7784
```java
7885
class Solution {
79-
private int[] cost;
80-
private int n;
81-
private int ans;
82-
8386
public int minIncrements(int n, int[] cost) {
84-
this.n = n;
85-
this.cost = cost;
86-
dfs(1);
87-
return ans;
88-
}
89-
90-
private int dfs(int i) {
91-
if ((i << 1) > n) {
92-
return cost[i - 1];
87+
int ans = 0;
88+
for (int i = n >> 1; i > 0; --i) {
89+
int l = i << 1, r = i << 1 | 1;
90+
ans += Math.abs(cost[l - 1] - cost[r - 1]);
91+
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
9392
}
94-
int l = dfs(i << 1);
95-
int r = dfs(i << 1 | 1);
96-
ans += Math.max(l, r) - Math.min(l, r);
97-
return cost[i - 1] + Math.max(l, r);
93+
return ans;
9894
}
9995
}
10096
```
@@ -104,49 +100,42 @@ class Solution {
104100
public:
105101
int minIncrements(int n, vector<int>& cost) {
106102
int ans = 0;
107-
function<int(int)> dfs = [&](int i) -> int {
108-
if ((i << 1) > n) {
109-
return cost[i - 1];
110-
}
111-
int l = dfs(i << 1);
112-
int r = dfs(i << 1 | 1);
113-
ans += max(l, r) - min(l, r);
114-
return cost[i - 1] + max(l, r);
115-
};
116-
dfs(1);
103+
for (int i = n >> 1; i > 0; --i) {
104+
int l = i << 1, r = i << 1 | 1;
105+
ans += abs(cost[l - 1] - cost[r - 1]);
106+
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
107+
}
117108
return ans;
118109
}
119110
};
120111
```
121112
122113
```go
123114
func minIncrements(n int, cost []int) (ans int) {
124-
var dfs func(int) int
125-
dfs = func(i int) int {
126-
if (i << 1) > n {
127-
return cost[i-1]
128-
}
129-
l, r := dfs(i<<1), dfs(i<<1|1)
130-
ans += max(l, r) - min(l, r)
131-
return cost[i-1] + max(l, r)
115+
for i := n >> 1; i > 0; i-- {
116+
l, r := i<<1, i<<1|1
117+
ans += abs(cost[l-1] - cost[r-1])
118+
cost[i-1] += max(cost[l-1], cost[r-1])
132119
}
133-
dfs(1)
134-
return ans
120+
return
121+
}
122+
123+
func abs(x int) int {
124+
if x < 0 {
125+
return -x
126+
}
127+
return x
135128
}
136129
```
137130

138131
```ts
139132
function minIncrements(n: number, cost: number[]): number {
140133
let ans = 0;
141-
const dfs = (i: number): number => {
142-
if (i << 1 > n) {
143-
return cost[i - 1];
144-
}
145-
const [a, b] = [dfs(i << 1), dfs((i << 1) | 1)];
146-
ans += Math.max(a, b) - Math.min(a, b);
147-
return cost[i - 1] + Math.max(a, b);
148-
};
149-
dfs(1);
134+
for (let i = n >> 1; i; --i) {
135+
const [l, r] = [i << 1, (i << 1) | 1];
136+
ans += Math.abs(cost[l - 1] - cost[r - 1]);
137+
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
138+
}
150139
return ans;
151140
}
152141
```

solution/2600-2699/2673.Make Costs of Paths Equal in a Binary Tree/Solution.cpp

+5-10
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@ class Solution {
22
public:
33
int minIncrements(int n, vector<int>& cost) {
44
int ans = 0;
5-
function<int(int)> dfs = [&](int i) -> int {
6-
if ((i << 1) > n) {
7-
return cost[i - 1];
8-
}
9-
int l = dfs(i << 1);
10-
int r = dfs(i << 1 | 1);
11-
ans += max(l, r) - min(l, r);
12-
return cost[i - 1] + max(l, r);
13-
};
14-
dfs(1);
5+
for (int i = n >> 1; i > 0; --i) {
6+
int l = i << 1, r = i << 1 | 1;
7+
ans += abs(cost[l - 1] - cost[r - 1]);
8+
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
9+
}
1510
return ans;
1611
}
1712
};
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
func minIncrements(n int, cost []int) (ans int) {
2-
var dfs func(int) int
3-
dfs = func(i int) int {
4-
if (i << 1) > n {
5-
return cost[i-1]
6-
}
7-
l, r := dfs(i<<1), dfs(i<<1|1)
8-
ans += max(l, r) - min(l, r)
9-
return cost[i-1] + max(l, r)
2+
for i := n >> 1; i > 0; i-- {
3+
l, r := i<<1, i<<1|1
4+
ans += abs(cost[l-1] - cost[r-1])
5+
cost[i-1] += max(cost[l-1], cost[r-1])
106
}
11-
dfs(1)
12-
return ans
7+
return
8+
}
9+
10+
func abs(x int) int {
11+
if x < 0 {
12+
return -x
13+
}
14+
return x
1315
}
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
11
class Solution {
2-
private int[] cost;
3-
private int n;
4-
private int ans;
5-
62
public int minIncrements(int n, int[] cost) {
7-
this.n = n;
8-
this.cost = cost;
9-
dfs(1);
10-
return ans;
11-
}
12-
13-
private int dfs(int i) {
14-
if ((i << 1) > n) {
15-
return cost[i - 1];
3+
int ans = 0;
4+
for (int i = n >> 1; i > 0; --i) {
5+
int l = i << 1, r = i << 1 | 1;
6+
ans += Math.abs(cost[l - 1] - cost[r - 1]);
7+
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
168
}
17-
int l = dfs(i << 1);
18-
int r = dfs(i << 1 | 1);
19-
ans += Math.max(l, r) - Math.min(l, r);
20-
return cost[i - 1] + Math.max(l, r);
9+
return ans;
2110
}
2211
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
class Solution:
22
def minIncrements(self, n: int, cost: List[int]) -> int:
3-
def dfs(i: int) -> int:
4-
if (i << 1) > n:
5-
return cost[i - 1]
6-
l, r = dfs(i << 1), dfs(i << 1 | 1)
7-
nonlocal ans
8-
ans += max(l, r) - min(l, r)
9-
return cost[i - 1] + max(l, r)
10-
113
ans = 0
12-
dfs(1)
4+
for i in range(n >> 1, 0, -1):
5+
l, r = i << 1, i << 1 | 1
6+
ans += abs(cost[l - 1] - cost[r - 1])
7+
cost[i - 1] += max(cost[l - 1], cost[r - 1])
138
return ans

0 commit comments

Comments
 (0)