From 9f696cdd6d1bfcd7e2747e5c2a9084beafccb1f7 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 15 Sep 2021 20:12:10 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1168.Optimize Water Distribution in a Village --- basic/searching/BinarySearch/README.md | 8 +- .../README.md | 194 +++++++++++++++++- .../README_EN.md | 137 ++++++++++++- .../Solution.cpp | 28 +++ .../Solution.go | 34 +++ .../Solution.java | 39 ++++ .../Solution.py | 23 +++ 7 files changed, 457 insertions(+), 6 deletions(-) create mode 100644 solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.cpp create mode 100644 solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.go create mode 100644 solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.java create mode 100644 solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.py diff --git a/basic/searching/BinarySearch/README.md b/basic/searching/BinarySearch/README.md index 6837031fd84a2..f7ad9df5ff741 100644 --- a/basic/searching/BinarySearch/README.md +++ b/basic/searching/BinarySearch/README.md @@ -44,11 +44,13 @@ int search(int left, int right) { 1. 写出循环条件:`while (left < right)`,注意是 `left < right`,而非 `left <= right`; 1. 循环体内,先无脑写出 `mid = (left + right) >> 1`; -1. 根据具体题目,实现 `check()` 函数(有时很简单的逻辑,可以不定义函数),想一下究竟要用 `left = mid`(模板二) 还是 `right = mid`(模板一); - - 如果 `left = mid`,那么无脑写出 else 语句 `right = mid - 1`,并且在 mid 计算时补充 +1,即 `mid = (left + right + 1) >> 1`; - - 如果 `right = mid`,那么无脑写出 else 语句 `left = mid + 1`,并且不需要更改 mid 的计算; +1. 根据具体题目,实现 `check()` 函数(有时很简单的逻辑,可以不定义 `check`),想一下究竟要用 `right = mid`(模板 1) 还是 `left = mid`(模板 2); + - 如果 `right = mid`,那么无脑写出 else 语句 `left = mid + 1`,并且不需要更改 mid 的计算,即保持 `mid = (left + right) >> 1`; + - 如果 `left = mid`,那么无脑写出 else 语句 `right = mid - 1`,并且在 mid 计算时补充 +1,即 `mid = (left + right + 1) >> 1`。 1. 循环结束时,left 与 right 相等。 +注意,这两个模板的优点是始终保持答案位于二分区间内,二分结束条件对应的值恰好在答案所处的位置。 对于可能无解的情况,只要判断二分结束后的 left 或者 right 是否满足题意即可。 + ## 例题 - [在排序数组中查找元素的第一个和最后一个位置](/solution/0000-0099/0034.Find%20First%20and%20Last%20Position%20of%20Element%20in%20Sorted%20Array/README.md) diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/README.md b/solution/1100-1199/1168.Optimize Water Distribution in a Village/README.md index a5cc967a77990..a9c6d4dcc0156 100644 --- a/solution/1100-1199/1168.Optimize Water Distribution in a Village/README.md +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/README.md @@ -44,11 +44,71 @@
  • pipes[i][0] != pipes[i][1]
  • - ## 解法 +并查集。 + +模板 1——朴素并查集: + +```python +# 初始化,p存储每个点的父节点 +p = list(range(n)) + +# 返回x的祖宗节点 +def find(x): + if p[x] != x: + # 路径压缩 + p[x] = find(p[x]) + return p[x] + +# 合并a和b所在的两个集合 +p[find(a)] = find(b) +``` + +模板 2——维护 size 的并查集: + +```python +# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量 +p = list(range(n)) +size = [1] * n + +# 返回x的祖宗节点 +def find(x): + if p[x] != x: + # 路径压缩 + p[x] = find(p[x]) + return p[x] + +# 合并a和b所在的两个集合 +if find(a) != find(b): + size[find(b)] += size[find(a)] + p[find(a)] = find(b) +``` + +模板 3——维护到祖宗节点距离的并查集: + +```python +# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离 +p = list(range(n)) +d = [0] * n + +# 返回x的祖宗节点 +def find(x): + if p[x] != x: + t = find(p[x]) + d[x] += d[p[x]] + p[x] = t + return p[x] + +# 合并a和b所在的两个集合 +p[find(a)] = find(b) +d[find(a)] = distance +``` + +对于本题,可以将节点 0 视为水库,水库到房子间的成本等于房子内建造水井的成本。因此此题可以转换为最小生成树问题。 + ### **Python3** @@ -56,7 +116,29 @@ ```python +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + for i, w in enumerate(wells): + pipes.append([0, i + 1, w]) + pipes.sort(key=lambda x: x[2]) + + p = list(range(n + 1)) + def find(x): + if p[x] != x: + p[x] = find(p[x]) + return p[x] + + res = 0 + for u, v, w in pipes: + if find(u) == find(v): + continue + p[find(u)] = find(v) + res += w + n -= 1 + if n == 0: + break + return res ``` ### **Java** @@ -64,7 +146,117 @@ ```java +class Solution { + private int[] p; + + public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) { + int[][] all = new int[pipes.length + n][3]; + int idx = 0; + for (int[] pipe : pipes) { + all[idx++] = pipe; + } + for (int j = 0; j < n; ++j) { + all[idx++] = new int[]{0, j + 1, wells[j]}; + } + p = new int[n + 1]; + for (int i = 0; i < p.length; ++i) { + p[i] = i; + } + Arrays.sort(all, Comparator.comparingInt(a -> a[2])); + int res = 0; + for (int[] e : all) { + if (find(e[0]) == find(e[1])) { + continue; + } + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) { + break; + } + } + return res; + } + + private int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector p; + + int minCostToSupplyWater(int n, vector& wells, vector>& pipes) { + p.resize(n + 1); + for (int i = 0; i < p.size(); ++i) p[i] = i; + for (int i = 0; i < n; ++i) pipes.push_back({0, i + 1, wells[i]}); + sort(pipes.begin(), pipes.end(), [](const auto& a, const auto& b) { + return a[2] < b[2]; + }); + int res = 0; + for (auto e : pipes) + { + if (find(e[0]) == find(e[1])) continue; + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) break; + } + return res; + } + + int find(int x) { + if (p[x] != x) p[x] = find(p[x]); + return p[x]; + } +}; +``` + +### **Go** + +```go +var p []int + +func minCostToSupplyWater(n int, wells []int, pipes [][]int) int { + p = make([]int, n+1) + for i := 0; i < len(p); i++ { + p[i] = i + } + for i, w := range wells { + pipes = append(pipes, []int{0, i + 1, w}) + } + sort.Slice(pipes, func(i, j int) bool { + return pipes[i][2] < pipes[j][2] + }) + res := 0 + for _, e := range pipes { + if find(e[0]) == find(e[1]) { + continue + } + p[find(e[0])] = find(e[1]) + res += e[2] + n-- + if n == 0 { + break + } + } + return res +} +func find(x int) int { + if p[x] != x { + p[x] = find(p[x]) + } + return p[x] +} ``` ### **...** diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/README_EN.md b/solution/1100-1199/1168.Optimize Water Distribution in a Village/README_EN.md index 229cf49778e1c..0a72c849d3eee 100644 --- a/solution/1100-1199/1168.Optimize Water Distribution in a Village/README_EN.md +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/README_EN.md @@ -37,21 +37,154 @@ The best strategy is to build a well in the first house with cost 1 and connect
  • house1j != house2j
  • - ## Solutions +Union find. + ### **Python3** ```python - +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + for i, w in enumerate(wells): + pipes.append([0, i + 1, w]) + pipes.sort(key=lambda x: x[2]) + + p = list(range(n + 1)) + + def find(x): + if p[x] != x: + p[x] = find(p[x]) + return p[x] + + res = 0 + for u, v, w in pipes: + if find(u) == find(v): + continue + p[find(u)] = find(v) + res += w + n -= 1 + if n == 0: + break + return res ``` ### **Java** ```java +class Solution { + private int[] p; + + public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) { + int[][] all = new int[pipes.length + n][3]; + int idx = 0; + for (int[] pipe : pipes) { + all[idx++] = pipe; + } + for (int j = 0; j < n; ++j) { + all[idx++] = new int[]{0, j + 1, wells[j]}; + } + p = new int[n + 1]; + for (int i = 0; i < p.length; ++i) { + p[i] = i; + } + Arrays.sort(all, Comparator.comparingInt(a -> a[2])); + int res = 0; + for (int[] e : all) { + if (find(e[0]) == find(e[1])) { + continue; + } + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) { + break; + } + } + return res; + } + + private int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector p; + + int minCostToSupplyWater(int n, vector& wells, vector>& pipes) { + p.resize(n + 1); + for (int i = 0; i < p.size(); ++i) p[i] = i; + for (int i = 0; i < n; ++i) pipes.push_back({0, i + 1, wells[i]}); + sort(pipes.begin(), pipes.end(), [](const auto& a, const auto& b) { + return a[2] < b[2]; + }); + int res = 0; + for (auto e : pipes) + { + if (find(e[0]) == find(e[1])) continue; + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) break; + } + return res; + } + + int find(int x) { + if (p[x] != x) p[x] = find(p[x]); + return p[x]; + } +}; +``` +### **Go** + +```go +var p []int + +func minCostToSupplyWater(n int, wells []int, pipes [][]int) int { + p = make([]int, n+1) + for i := 0; i < len(p); i++ { + p[i] = i + } + for i, w := range wells { + pipes = append(pipes, []int{0, i + 1, w}) + } + sort.Slice(pipes, func(i, j int) bool { + return pipes[i][2] < pipes[j][2] + }) + res := 0 + for _, e := range pipes { + if find(e[0]) == find(e[1]) { + continue + } + p[find(e[0])] = find(e[1]) + res += e[2] + n-- + if n == 0 { + break + } + } + return res +} + +func find(x int) int { + if p[x] != x { + p[x] = find(p[x]) + } + return p[x] +} ``` ### **...** diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.cpp b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.cpp new file mode 100644 index 0000000000000..d3b8a34e9926a --- /dev/null +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + vector p; + + int minCostToSupplyWater(int n, vector& wells, vector>& pipes) { + p.resize(n + 1); + for (int i = 0; i < p.size(); ++i) p[i] = i; + for (int i = 0; i < n; ++i) pipes.push_back({0, i + 1, wells[i]}); + sort(pipes.begin(), pipes.end(), [](const auto& a, const auto& b) { + return a[2] < b[2]; + }); + int res = 0; + for (auto e : pipes) + { + if (find(e[0]) == find(e[1])) continue; + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) break; + } + return res; + } + + int find(int x) { + if (p[x] != x) p[x] = find(p[x]); + return p[x]; + } +}; \ No newline at end of file diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.go b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.go new file mode 100644 index 0000000000000..c4116329e915c --- /dev/null +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.go @@ -0,0 +1,34 @@ +var p []int + +func minCostToSupplyWater(n int, wells []int, pipes [][]int) int { + p = make([]int, n+1) + for i := 0; i < len(p); i++ { + p[i] = i + } + for i, w := range wells { + pipes = append(pipes, []int{0, i + 1, w}) + } + sort.Slice(pipes, func(i, j int) bool { + return pipes[i][2] < pipes[j][2] + }) + res := 0 + for _, e := range pipes { + if find(e[0]) == find(e[1]) { + continue + } + p[find(e[0])] = find(e[1]) + res += e[2] + n-- + if n == 0 { + break + } + } + return res +} + +func find(x int) int { + if p[x] != x { + p[x] = find(p[x]) + } + return p[x] +} \ No newline at end of file diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.java b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.java new file mode 100644 index 0000000000000..ab4b4e7f88d9d --- /dev/null +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.java @@ -0,0 +1,39 @@ +class Solution { + private int[] p; + + public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) { + int[][] all = new int[pipes.length + n][3]; + int idx = 0; + for (int[] pipe : pipes) { + all[idx++] = pipe; + } + for (int j = 0; j < n; ++j) { + all[idx++] = new int[]{0, j + 1, wells[j]}; + } + p = new int[n + 1]; + for (int i = 0; i < p.length; ++i) { + p[i] = i; + } + Arrays.sort(all, Comparator.comparingInt(a -> a[2])); + int res = 0; + for (int[] e : all) { + if (find(e[0]) == find(e[1])) { + continue; + } + p[find(e[0])] = find(e[1]); + res += e[2]; + --n; + if (n == 0) { + break; + } + } + return res; + } + + private int find(int x) { + if (p[x] != x) { + p[x] = find(p[x]); + } + return p[x]; + } +} \ No newline at end of file diff --git a/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.py b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.py new file mode 100644 index 0000000000000..672938f3a7b9e --- /dev/null +++ b/solution/1100-1199/1168.Optimize Water Distribution in a Village/Solution.py @@ -0,0 +1,23 @@ +class Solution: + def minCostToSupplyWater(self, n: int, wells: List[int], pipes: List[List[int]]) -> int: + for i, w in enumerate(wells): + pipes.append([0, i + 1, w]) + pipes.sort(key=lambda x: x[2]) + + p = list(range(n + 1)) + + def find(x): + if p[x] != x: + p[x] = find(p[x]) + return p[x] + + res = 0 + for u, v, w in pipes: + if find(u) == find(v): + continue + p[find(u)] = find(v) + res += w + n -= 1 + if n == 0: + break + return res