Skip to content

feat: add solutions to lc problem: No.2673 #2373

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

Merged
merged 1 commit into from
Feb 24, 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
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,43 @@

## 解法

### 方法一
### 方法一:贪心

根据题目描述,我们需要计算最小的增加次数,使得根节点到每个叶子节点的路径值相等。

根节点到每个叶子节点的路径值相等,实际上等价于以任意节点为根节点的子树到该子树的每个叶子节点的路径值相等。

为什么呢?我们可以用反证法来证明。假设存在一个节点 $x$,以它为根节点的子树到某个叶子节点的路径值不相等,那么也就存在着根节点到叶子节点的路径值不相等的情况,这与“根节点到每个叶子节点的路径值相等”矛盾。因此假设不成立,以任意节点为根节点的子树到该子树的每个叶子节点的路径值相等。

我们可以从树的底部开始,逐层向上计算增加次数。对于每个非叶子节点,我们可以计算它的左右孩子节点的路径值,增加的次数为两者路径值的差值,然后将左右孩子节点的路径值更新为两者中的较大值。

最后返回总的增加的次数即可。

时间复杂度 $O(n)$,其中 $n$ 为节点数。空间复杂度 $O(1)$。

<!-- tabs:start -->

```python
class Solution:
def minIncrements(self, n: int, cost: List[int]) -> int:
def dfs(i: int) -> int:
if (i << 1) > n:
return cost[i - 1]
l, r = dfs(i << 1), dfs(i << 1 | 1)
nonlocal ans
ans += max(l, r) - min(l, r)
return cost[i - 1] + max(l, r)

ans = 0
dfs(1)
for i in range(n >> 1, 0, -1):
l, r = i << 1, i << 1 | 1
ans += abs(cost[l - 1] - cost[r - 1])
cost[i - 1] += max(cost[l - 1], cost[r - 1])
return ans
```

```java
class Solution {
private int[] cost;
private int n;
private int ans;

public int minIncrements(int n, int[] cost) {
this.n = n;
this.cost = cost;
dfs(1);
return ans;
}

private int dfs(int i) {
if ((i << 1) > n) {
return cost[i - 1];
int ans = 0;
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += Math.abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += Math.max(l, r) - Math.min(l, r);
return cost[i - 1] + Math.max(l, r);
return ans;
}
}
```
Expand All @@ -112,49 +108,42 @@ class Solution {
public:
int minIncrements(int n, vector<int>& cost) {
int ans = 0;
function<int(int)> dfs = [&](int i) -> int {
if ((i << 1) > n) {
return cost[i - 1];
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += max(l, r) - min(l, r);
return cost[i - 1] + max(l, r);
};
dfs(1);
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
}
return ans;
}
};
```

```go
func minIncrements(n int, cost []int) (ans int) {
var dfs func(int) int
dfs = func(i int) int {
if (i << 1) > n {
return cost[i-1]
}
l, r := dfs(i<<1), dfs(i<<1|1)
ans += max(l, r) - min(l, r)
return cost[i-1] + max(l, r)
for i := n >> 1; i > 0; i-- {
l, r := i<<1, i<<1|1
ans += abs(cost[l-1] - cost[r-1])
cost[i-1] += max(cost[l-1], cost[r-1])
}
dfs(1)
return ans
return
}

func abs(x int) int {
if x < 0 {
return -x
}
return x
}
```

```ts
function minIncrements(n: number, cost: number[]): number {
let ans = 0;
const dfs = (i: number): number => {
if (i << 1 > n) {
return cost[i - 1];
}
const [a, b] = [dfs(i << 1), dfs((i << 1) | 1)];
ans += Math.max(a, b) - Math.min(a, b);
return cost[i - 1] + Math.max(a, b);
};
dfs(1);
for (let i = n >> 1; i; --i) {
const [l, r] = [i << 1, (i << 1) | 1];
ans += Math.abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
}
return ans;
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,47 +54,43 @@ It can be shown that this is the minimum answer we can achieve.

## Solutions

### Solution 1
### Solution 1: Greedy Algorithm

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.

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.

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.

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.

Finally, return the total number of increments.

The time complexity is $O(n)$, where $n$ is the number of nodes. The space complexity is $O(1)$.

<!-- tabs:start -->

```python
class Solution:
def minIncrements(self, n: int, cost: List[int]) -> int:
def dfs(i: int) -> int:
if (i << 1) > n:
return cost[i - 1]
l, r = dfs(i << 1), dfs(i << 1 | 1)
nonlocal ans
ans += max(l, r) - min(l, r)
return cost[i - 1] + max(l, r)

ans = 0
dfs(1)
for i in range(n >> 1, 0, -1):
l, r = i << 1, i << 1 | 1
ans += abs(cost[l - 1] - cost[r - 1])
cost[i - 1] += max(cost[l - 1], cost[r - 1])
return ans
```

```java
class Solution {
private int[] cost;
private int n;
private int ans;

public int minIncrements(int n, int[] cost) {
this.n = n;
this.cost = cost;
dfs(1);
return ans;
}

private int dfs(int i) {
if ((i << 1) > n) {
return cost[i - 1];
int ans = 0;
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += Math.abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += Math.max(l, r) - Math.min(l, r);
return cost[i - 1] + Math.max(l, r);
return ans;
}
}
```
Expand All @@ -104,49 +100,42 @@ class Solution {
public:
int minIncrements(int n, vector<int>& cost) {
int ans = 0;
function<int(int)> dfs = [&](int i) -> int {
if ((i << 1) > n) {
return cost[i - 1];
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += max(l, r) - min(l, r);
return cost[i - 1] + max(l, r);
};
dfs(1);
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
}
return ans;
}
};
```

```go
func minIncrements(n int, cost []int) (ans int) {
var dfs func(int) int
dfs = func(i int) int {
if (i << 1) > n {
return cost[i-1]
}
l, r := dfs(i<<1), dfs(i<<1|1)
ans += max(l, r) - min(l, r)
return cost[i-1] + max(l, r)
for i := n >> 1; i > 0; i-- {
l, r := i<<1, i<<1|1
ans += abs(cost[l-1] - cost[r-1])
cost[i-1] += max(cost[l-1], cost[r-1])
}
dfs(1)
return ans
return
}

func abs(x int) int {
if x < 0 {
return -x
}
return x
}
```

```ts
function minIncrements(n: number, cost: number[]): number {
let ans = 0;
const dfs = (i: number): number => {
if (i << 1 > n) {
return cost[i - 1];
}
const [a, b] = [dfs(i << 1), dfs((i << 1) | 1)];
ans += Math.max(a, b) - Math.min(a, b);
return cost[i - 1] + Math.max(a, b);
};
dfs(1);
for (let i = n >> 1; i; --i) {
const [l, r] = [i << 1, (i << 1) | 1];
ans += Math.abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
}
return ans;
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ class Solution {
public:
int minIncrements(int n, vector<int>& cost) {
int ans = 0;
function<int(int)> dfs = [&](int i) -> int {
if ((i << 1) > n) {
return cost[i - 1];
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += max(l, r) - min(l, r);
return cost[i - 1] + max(l, r);
};
dfs(1);
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += max(cost[l - 1], cost[r - 1]);
}
return ans;
}
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
func minIncrements(n int, cost []int) (ans int) {
var dfs func(int) int
dfs = func(i int) int {
if (i << 1) > n {
return cost[i-1]
}
l, r := dfs(i<<1), dfs(i<<1|1)
ans += max(l, r) - min(l, r)
return cost[i-1] + max(l, r)
for i := n >> 1; i > 0; i-- {
l, r := i<<1, i<<1|1
ans += abs(cost[l-1] - cost[r-1])
cost[i-1] += max(cost[l-1], cost[r-1])
}
dfs(1)
return ans
return
}

func abs(x int) int {
if x < 0 {
return -x
}
return x
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
class Solution {
private int[] cost;
private int n;
private int ans;

public int minIncrements(int n, int[] cost) {
this.n = n;
this.cost = cost;
dfs(1);
return ans;
}

private int dfs(int i) {
if ((i << 1) > n) {
return cost[i - 1];
int ans = 0;
for (int i = n >> 1; i > 0; --i) {
int l = i << 1, r = i << 1 | 1;
ans += Math.abs(cost[l - 1] - cost[r - 1]);
cost[i - 1] += Math.max(cost[l - 1], cost[r - 1]);
}
int l = dfs(i << 1);
int r = dfs(i << 1 | 1);
ans += Math.max(l, r) - Math.min(l, r);
return cost[i - 1] + Math.max(l, r);
return ans;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
class Solution:
def minIncrements(self, n: int, cost: List[int]) -> int:
def dfs(i: int) -> int:
if (i << 1) > n:
return cost[i - 1]
l, r = dfs(i << 1), dfs(i << 1 | 1)
nonlocal ans
ans += max(l, r) - min(l, r)
return cost[i - 1] + max(l, r)

ans = 0
dfs(1)
for i in range(n >> 1, 0, -1):
l, r = i << 1, i << 1 | 1
ans += abs(cost[l - 1] - cost[r - 1])
cost[i - 1] += max(cost[l - 1], cost[r - 1])
return ans
Loading