Merge pull request #752 from youngqqcn/master

0684.冗余连接, 0685.冗余连接II,增加Java, Golang, Python实现
This commit is contained in:
程序员Carl
2021-09-17 09:09:20 +08:00
committed by GitHub
3 changed files with 473 additions and 8 deletions

View File

@ -10,6 +10,9 @@
# 684.冗余连接
[力扣题目链接](https://leetcode-cn.com/problems/redundant-connection/)
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n 个节点 (节点值 1n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。
@ -140,16 +143,161 @@ public:
## Java
```java
class Solution {
private int n; // 节点数量3 到 1000
private int[] father;
public Solution() {
n = 1005;
father = new int[n];
// 并查集初始化
for (int i = 0; i < n; ++i) {
father[i] = i;
}
}
// 并查集里寻根的过程
private int find(int u) {
if(u == father[u]) {
return u;
}
father[u] = find(father[u]);
return father[u];
}
// 将v->u 这条边加入并查集
private void join(int u, int v) {
u = find(u);
v = find(v);
if (u == v) return ;
father[v] = u;
}
// 判断 u 和 v是否找到同一个根本题用不上
private Boolean same(int u, int v) {
u = find(u);
v = find(v);
return u == v;
}
public int[] findRedundantConnection(int[][] edges) {
for (int i = 0; i < edges.length; i++) {
if (same(edges[i][0], edges[i][1])) {
return edges[i];
} else {
join(edges[i][0], edges[i][1]);
}
}
return null;
}
}
```
## Python
```python
class Solution:
def __init__(self):
"""
初始化
"""
self.n = 1005
self.father = [i for i in range(self.n)]
def find(self, u):
"""
并查集里寻根的过程
"""
if u == self.father[u]:
return u
self.father[u] = self.find(self.father[u])
return self.father[u]
def join(self, u, v):
"""
将v->u 这条边加入并查集
"""
u = self.find(u)
v = self.find(v)
if u == v : return
self.father[v] = u
pass
def same(self, u, v ):
"""
判断 u 和 v是否找到同一个根本题用不上
"""
u = self.find(u)
v = self.find(v)
return u == v
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
for i in range(len(edges)):
if self.same(edges[i][0], edges[i][1]) :
return edges[i]
else :
self.join(edges[i][0], edges[i][1])
return []
```
## Go
```go
// 全局变量
var (
n = 1005 // 节点数量3 到 1000
father = make([]int, 1005)
)
// 并查集初始化
func initialize() {
for i := 0; i < n; i++ {
father[i] = i
}
}
// 并查集里寻根的过程
func find(u int) int {
if u == father[u] {
return u
}
father[u] = find(father[u])
return father[u]
}
// 将v->u 这条边加入并查集
func join(u, v int) {
u = find(u)
v = find(v)
if u == v {
return
}
father[v] = u
}
// 判断 u 和 v是否找到同一个根本题用不上
func same(u, v int) bool {
u = find(u)
v = find(v)
return u == v
}
func findRedundantConnection(edges [][]int) []int {
initialize()
for i := 0; i < len(edges); i++ {
if same(edges[i][0], edges[i][1]) {
return edges[i]
} else {
join(edges[i][0], edges[i][1])
}
}
return []int{}
}
```
## JavaScript

View File

@ -39,7 +39,7 @@
**这说明题目中的图原本是是一棵树,只不过在不增加节点的情况下多加了一条边!**
还有**若有多个答案,返回最后出现在给定二维数组的答案。**这说明在两边都可以删除的情况下,要删顺序靠后的!
还有**若有多个答案,返回最后出现在给定二维数组的答案。**这说明在两边都可以删除的情况下,要删顺序靠后的!
那么有如下三种情况前两种情况是出现入度为2的点如图
@ -58,7 +58,7 @@
首先先计算节点的入度,代码如下:
```CPP
```cpp
int inDegree[N] = {0}; // 记录节点入度
n = edges.size(); // 边的数量
for (int i = 0; i < n; i++) {
@ -70,7 +70,7 @@ for (int i = 0; i < n; i++) {
代码如下:
```CPP
```cpp
vector<int> vec; // 记录入度为2的边如果有的话就两条边
// 找入度为2的节点所对应的边注意要倒叙因为优先返回最后出现在二维数组中的答案
for (int i = n - 1; i >= 0; i--) {
@ -112,7 +112,7 @@ vector<int> getRemoveEdge(const vector<vector<int>>& edges)
本题C++代码如下:(详细注释了)
```CPP
```cpp
class Solution {
private:
static const int N = 1010; // 如题二维数组大小的在3到1000范围内
@ -174,7 +174,7 @@ public:
inDegree[edges[i][1]]++; // 统计入度
}
vector<int> vec; // 记录入度为2的边如果有的话就两条边
// 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案
// 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案
for (int i = n - 1; i >= 0; i--) {
if (inDegree[edges[i][1]] == 2) {
vec.push_back(i);
@ -203,16 +203,313 @@ public:
## Java
```java
class Solution {
private static final int N = 1010; // 如题二维数组大小的在3到1000范围内
private int[] father;
public Solution() {
father = new int[N];
// 并查集初始化
for (int i = 0; i < N; ++i) {
father[i] = i;
}
}
// 并查集里寻根的过程
private int find(int u) {
if(u == father[u]) {
return u;
}
father[u] = find(father[u]);
return father[u];
}
// 将v->u 这条边加入并查集
private void join(int u, int v) {
u = find(u);
v = find(v);
if (u == v) return ;
father[v] = u;
}
// 判断 u 和 v是否找到同一个根本题用不上
private Boolean same(int u, int v) {
u = find(u);
v = find(v);
return u == v;
}
/**
* 初始化并查集
*/
private void initFather() {
// 并查集初始化
for (int i = 0; i < N; ++i) {
father[i] = i;
}
}
/**
* 在有向图里找到删除的那条边,使其变成树
* @param edges
* @return 要删除的边
*/
private int[] getRemoveEdge(int[][] edges) {
initFather();
for(int i = 0; i < edges.length; i++) {
if(same(edges[i][0], edges[i][1])) { // 构成有向环了,就是要删除的边
return edges[i];
}
join(edges[i][0], edges[i][1]);
}
return null;
}
/**
* 删一条边之后判断是不是树
* @param edges
* @param deleteEdge 要删除的边
* @return true: 是树, false 不是树
*/
private Boolean isTreeAfterRemoveEdge(int[][] edges, int deleteEdge)
{
initFather();
for(int i = 0; i < edges.length; i++)
{
if(i == deleteEdge) continue;
if(same(edges[i][0], edges[i][1])) { // 构成有向环了,一定不是树
return false;
}
join(edges[i][0], edges[i][1]);
}
return true;
}
public int[] findRedundantDirectedConnection(int[][] edges) {
int[] inDegree = new int[N];
for(int i = 0; i < edges.length; i++)
{
// 入度
inDegree[ edges[i][1] ] += 1;
}
// 找入度为2的节点所对应的边注意要倒序因为优先返回最后出现在二维数组中的答案
ArrayList<Integer> twoDegree = new ArrayList<Integer>();
for(int i = edges.length - 1; i >= 0; i--)
{
if(inDegree[edges[i][1]] == 2) {
twoDegree.add(i);
}
}
// 处理图中情况1 和 情况2
// 如果有入度为2的节点那么一定是两条边里删一个看删哪个可以构成树
if(!twoDegree.isEmpty())
{
if(isTreeAfterRemoveEdge(edges, twoDegree.get(0))) {
return edges[ twoDegree.get(0)];
}
return edges[ twoDegree.get(1)];
}
// 明确没有入度为2的情况那么一定有有向环找到构成环的边返回就可以了
return getRemoveEdge(edges);
}
}
```
## Python
```python
class Solution:
def __init__(self):
self.n = 1010
self.father = [i for i in range(self.n)]
def find(self, u: int):
"""
并查集里寻根的过程
"""
if u == self.father[u]:
return u
self.father[u] = self.find(self.father[u])
return self.father[u]
def join(self, u: int, v: int):
"""
将v->u 这条边加入并查集
"""
u = self.find(u)
v = self.find(v)
if u == v : return
self.father[v] = u
pass
def same(self, u: int, v: int ):
"""
判断 u 和 v是否找到同一个根本题用不上
"""
u = self.find(u)
v = self.find(v)
return u == v
def init_father(self):
self.father = [i for i in range(self.n)]
pass
def getRemoveEdge(self, edges: List[List[int]]) -> List[int]:
"""
在有向图里找到删除的那条边,使其变成树
"""
self.init_father()
for i in range(len(edges)):
if self.same(edges[i][0], edges[i][1]): # 构成有向环了,就是要删除的边
return edges[i]
self.join(edges[i][0], edges[i][1]);
return []
def isTreeAfterRemoveEdge(self, edges: List[List[int]], deleteEdge: int) -> bool:
"""
删一条边之后判断是不是树
"""
self.init_father()
for i in range(len(edges)):
if i == deleteEdge: continue
if self.same(edges[i][0], edges[i][1]): # 构成有向环了,一定不是树
return False
self.join(edges[i][0], edges[i][1]);
return True
def findRedundantDirectedConnection(self, edges: List[List[int]]) -> List[int]:
inDegree = [0 for i in range(self.n)]
for i in range(len(edges)):
inDegree[ edges[i][1] ] += 1
# 找入度为2的节点所对应的边注意要倒序因为优先返回最后出现在二维数组中的答案
towDegree = []
for i in range(len(edges))[::-1]:
if inDegree[edges[i][1]] == 2 :
towDegree.append(i)
# 处理图中情况1 和 情况2
# 如果有入度为2的节点那么一定是两条边里删一个看删哪个可以构成树
if len(towDegree) > 0:
if(self.isTreeAfterRemoveEdge(edges, towDegree[0])) :
return edges[towDegree[0]]
return edges[towDegree[1]]
# 明确没有入度为2的情况那么一定有有向环找到构成环的边返回就可以了
return self.getRemoveEdge(edges)
```
## Go
```go
// 全局变量
var (
n = 1010// 节点数量3 到 1000
father = make([]int, n)
)
// 并查集初始化
func initialize() {
for i := 0; i < n; i++ {
father[i] = i
}
}
// 并查集里寻根的过程
func find(u int) int {
if u == father[u] {
return u
}
father[u] = find(father[u])
return father[u]
}
// 将v->u 这条边加入并查集
func join(u, v int) {
u = find(u)
v = find(v)
if u == v {
return
}
father[v] = u
}
// 判断 u 和 v是否找到同一个根本题用不上
func same(u, v int) bool {
u = find(u)
v = find(v)
return u == v
}
// getRemoveEdge 在有向图里找到删除的那条边,使其变成树
func getRemoveEdge(edges [][]int) []int {
initialize()
for i := 0; i < len(edges); i++ { // 遍历所有的边
if same(edges[i][0], edges[i][1]) { // 构成有向环了,就是要删除的边
return edges[i]
}
join(edges[i][0], edges[i][1])
}
return []int{}
}
// isTreeAfterRemoveEdge 删一条边之后判断是不是树
func isTreeAfterRemoveEdge(edges [][]int, deleteEdge int) bool {
initialize()
for i := 0; i < len(edges); i++ {
if i == deleteEdge {
continue
}
if same(edges[i][0], edges[i][1]) { // 构成有向环了,一定不是树
return false
}
join(edges[i][0], edges[i][1])
}
return true
}
func findRedundantDirectedConnection(edges [][]int) []int {
inDegree := make([]int, len(father))
for i := 0; i < len(edges); i++ {
// 统计入度
inDegree[edges[i][1]] += 1
}
// 记录入度为2的边如果有的话就两条边
// 找入度为2的节点所对应的边注意要倒序因为优先返回最后出现在二维数组中的答案
twoDegree := make([]int, 0)
for i := len(edges) - 1; i >= 0; i-- {
if inDegree[edges[i][1]] == 2 {
twoDegree = append(twoDegree, i)
}
}
// 处理图中情况1 和 情况2
// 如果有入度为2的节点那么一定是两条边里删一个看删哪个可以构成树
if len(twoDegree) > 0 {
if isTreeAfterRemoveEdge(edges, twoDegree[0]) {
return edges[twoDegree[0]]
}
return edges[twoDegree[1]]
}
// 处理图中情况3
// 明确没有入度为2的情况那么一定有有向环找到构成环的边返回就可以了
return getRemoveEdge(edges)
}
```
## JavaScript

View File

@ -9,6 +9,8 @@
# 724.寻找数组的中心下标
[力扣题目链接](https://leetcode-cn.com/problems/find-pivot-index/)
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
@ -87,15 +89,15 @@ class Solution {
}
```
## Python
## Python3
```python3
```python
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
numSum = sum(nums) #数组总和
leftSum = 0
for i in range(len(nums)):
if numSum - leftSum -nums[i] == leftSum: #左右和相等
if numSum - leftSum -nums[i] == leftSum: #左右和相等
return i
leftSum += nums[i]
return -1
@ -104,6 +106,24 @@ class Solution:
## Go
```go
func pivotIndex(nums []int) int {
sum := 0
for _, v := range nums {
sum += v;
}
leftSum := 0 // 中心索引左半和
rightSum := 0 // 中心索引右半和
for i := 0; i < len(nums); i++ {
leftSum += nums[i]
rightSum = sum - leftSum + nums[i]
if leftSum == rightSum{
return i
}
}
return -1
}
```
## JavaScript