Add solution 1319

This commit is contained in:
YDZ
2021-01-23 16:03:06 +08:00
parent 228bde3678
commit d46930712e
27 changed files with 646 additions and 366 deletions

View File

@ -10,9 +10,9 @@ Given n non-negative integers representing an elevation map where the width of e
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
Example:
**Example**:
```c
```go
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
```
@ -23,7 +23,9 @@ Output: 6
## 解题思路
![](https://image.ibb.co/d6A2ZU/IMG-0139.jpg)
每个数组里面的元素值可以想象成一个左右都有壁的圆柱筒。例如上图中左边的第二个元素 1当前左边最大的元素是 2 ,所以 2 高度的水会装到 1 的上面(因为想象成了左右都有筒壁)。这道题的思路就是左指针从 0 开始往右扫,右指针从最右边开始往左扫。额外还需要 2 个变量分别记住左边最大的高度和右边最大高度。遍历扫数组元素的过程中,如果左指针的高度比右指针的高度小,就不断的移动左指针,否则移动右指针。循环的终止条件就是左右指针碰上以后就结束。只要数组中元素的高度比保存的局部最大高度小,就累加 res 的值,否则更新局部最大高度。最终解就是 res 的值。
- 每个数组里面的元素值可以想象成一个左右都有壁的圆柱筒。例如下图中左边的第二个元素 1当前左边最大的元素是 2 ,所以 2 高度的水会装到 1 的上面(因为想象成了左右都有筒壁)。这道题的思路就是左指针从 0 开始往右扫,右指针从最右边开始往左扫。额外还需要 2 个变量分别记住左边最大的高度和右边最大高度。遍历扫数组元素的过程中,如果左指针的高度比右指针的高度小,就不断的移动左指针,否则移动右指针。循环的终止条件就是左右指针碰上以后就结束。只要数组中元素的高度比保存的局部最大高度小,就累加 res 的值,否则更新局部最大高度。最终解就是 res 的值。
![](https://image.ibb.co/d6A2ZU/IMG-0139.jpg)
- 抽象一下,本题是想求针对每个 i找到它左边最大值 leftMax右边的最大值 rightMax然后 min(leftMaxrightMax) 为能够接到水的高度。left 和 right 指针是两边往中间移动的游标指针。最傻的解题思路是针对每个下标 i往左循环找到第一个最大值往右循环找到第一个最大值然后把这两个最大值取出最小者即为当前雨水的高度。这样做时间复杂度高浪费了很多循环。i 在从左往右的过程中,是可以动态维护最大值的。右边的最大值用右边的游标指针来维护。从左往右扫一遍下标,和,从两边往中间遍历一遍下标,是相同的结果,每个下标都遍历了一次。
![](https://img.halfrost.com/Leetcode/leetcode_42_1.png)
- 每个 i 的宽度固定为 1所以每个“坑”只需要求出高度即当前这个“坑”能积攒的雨水。最后依次将每个“坑”中的雨水相加即是能接到的雨水数。
![](https://img.halfrost.com/Leetcode/leetcode_42_0.png)

View File

@ -0,0 +1,24 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/template"
)
func makeConnected(n int, connections [][]int) int {
if n-1 > len(connections) {
return -1
}
uf, redundance := template.UnionFind{}, 0
uf.Init(n)
for _, connection := range connections {
if uf.Find(connection[0]) == uf.Find(connection[1]) {
redundance++
} else {
uf.Union(connection[0], connection[1])
}
}
if uf.TotalCount() == 1 || redundance < uf.TotalCount()-1 {
return 0
}
return uf.TotalCount() - 1
}

View File

@ -0,0 +1,63 @@
package leetcode
import (
"fmt"
"testing"
)
type question1319 struct {
para1319
ans1319
}
// para 是参数
// one 代表第一个参数
type para1319 struct {
n int
connections [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1319 struct {
one int
}
func Test_Problem1319(t *testing.T) {
qs := []question1319{
{
para1319{4, [][]int{{0, 1}, {0, 2}, {1, 2}}},
ans1319{1},
},
{
para1319{6, [][]int{{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}}},
ans1319{2},
},
{
para1319{6, [][]int{{0, 1}, {0, 2}, {0, 3}, {1, 2}}},
ans1319{-1},
},
{
para1319{5, [][]int{{0, 1}, {0, 2}, {3, 4}, {2, 3}}},
ans1319{0},
},
{
para1319{12, [][]int{{1, 5}, {1, 7}, {1, 2}, {1, 4}, {3, 7}, {4, 7}, {3, 5}, {0, 6}, {0, 1}, {0, 4}, {2, 6}, {0, 3}, {0, 2}}},
ans1319{4},
},
}
fmt.Printf("------------------------Leetcode Problem 1319------------------------\n")
for _, q := range qs {
_, p := q.ans1319, q.para1319
fmt.Printf("【input】:%v 【output】:%v\n", p, makeConnected(p.n, p.connections))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,90 @@
# [1319. Number of Operations to Make Network Connected](https://leetcode.com/problems/number-of-operations-to-make-network-connected/)
## 题目
There are `n` computers numbered from `0` to `n-1` connected by ethernet cables `connections` forming a network where `connections[i] = [a, b]` represents a connection between computers `a` and `b`. Any computer can reach any other computer directly or indirectly through the network.
Given an initial computer network `connections`. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected. Return the *minimum number of times* you need to do this in order to make all the computers connected. If it's not possible, return -1.
**Example 1:**
![https://assets.leetcode.com/uploads/2020/01/02/sample_1_1677.png](https://assets.leetcode.com/uploads/2020/01/02/sample_1_1677.png)
```
Input: n = 4, connections = [[0,1],[0,2],[1,2]]
Output: 1
Explanation: Remove cable between computer 1 and 2 and place between computers 1 and 3.
```
**Example 2:**
![https://assets.leetcode.com/uploads/2020/01/02/sample_2_1677.png](https://assets.leetcode.com/uploads/2020/01/02/sample_2_1677.png)
```
Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
Output: 2
```
**Example 3:**
```
Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2]]
Output: -1
Explanation: There are not enough cables.
```
**Example 4:**
```
Input: n = 5, connections = [[0,1],[0,2],[3,4],[2,3]]
Output: 0
```
**Constraints:**
- `1 <= n <= 10^5`
- `1 <= connections.length <= min(n*(n-1)/2, 10^5)`
- `connections[i].length == 2`
- `0 <= connections[i][0], connections[i][1] < n`
- `connections[i][0] != connections[i][1]`
- There are no repeated connections.
- No two computers are connected by more than one cable.
## 题目大意
用以太网线缆将 n 台计算机连接成一个网络计算机的编号从 0  n-1。线缆用 connections 表示其中 connections[i] = [a, b] 连接了计算机 a  b。网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。给你这个计算机网络的初始布线 connections你可以拔开任意两台直连计算机之间的线缆并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能则返回 -1 。
## 解题思路
- 很明显这题的解题思路是并查集。先将每个 connections 构建出并查集。构建中需要累加冗余的连接。例如 2 个节点已经连通,再连接这个集合中的任意 2 个节点就算冗余连接。冗余连接的线都可以移动,去连接还没有连通的节点。计算出冗余连接数,再根据并查集的集合总数,即可得出答案。
- 这一题答案有 3 种可能。第一种,所有点都在一个集合内,即全部连通,这时输出 0 。第二种,冗余的连接不够串起所有点,这时输出 -1 。第三种情况是可以连通的情况。 m 个集合需要连通,最少需要 m - 1 条线。如果冗余连接数大于 m - 1则输出 m - 1 即可。
## 代码
```go
package leetcode
import (
"github.com/halfrost/LeetCode-Go/template"
)
func makeConnected(n int, connections [][]int) int {
if n-1 > len(connections) {
return -1
}
uf, redundance := template.UnionFind{}, 0
uf.Init(n)
for _, connection := range connections {
if uf.Find(connection[0]) == uf.Find(connection[1]) {
redundance++
} else {
uf.Union(connection[0], connection[1])
}
}
if uf.TotalCount() == 1 || redundance < uf.TotalCount()-1 {
return 0
}
return uf.TotalCount() - 1
}
```