面向小白的力扣684. 冗余连接

227 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

今天,我们继续搞算法。

题目描述

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。

题目分析

这个题目是找出一条可以删去的边,使得剩余部分是一个树。

树可以看成是一个连通且 无环 的 无向 图。这句话很重要,后续有讲解。

那怎么来找呢?我们先使用出边数组构建出一个图,一条边一条边的构建,然后遍历这个图,如果成环,就返回这条边。

我们来分析一下这个题,去掉一条成环的边,它给了这个成环的图,如下:

  • edges = [[1,2], [1,3], [2,3]] 这是一个三条边的数组,如图所示成环,我们要删除一条边,使其成为一棵树,
  • 那我们怎么来做呢?可以先把这个图描述出来,一条一条的画,然后进行深度优先遍历,如果成环,说明该边就是需
  • 删除的边。
  • 一开始,加一条:1to2,2to1, 走1,标记,然后走2标记,2走1,1标记过结束,不成环。
  • 要注意2到1和1到2我们需要进行判重
  • 如果一个点走过了,一圈之后,还能走,而且也判重过,说明成环,就把那条边返回即可。 我们来实现一下

解题思路

  • 确定操作对象:本题中,操作对象1个edges
  • 确定操作条件:如果该点没走过,就走该点,如果要已经到达的点还有曾经到过的点就跳过。
  • 确定操作过程:操作过程就是深度优先遍历所有点。
  • 确定结果返回:成环则返回最终结果。

代码

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        //构造一个图
        int n =0;
        for(vector<int>& edge : edges){
            int a = edge[0];
            int b = edge[1];
           n = max(n,max(a,b));
        }

          to = vector<vector<int>>(n+1 ,vector<int>());
          visited =  vector<bool>(to.size(),false);

         for(vector<int>& edge : edges){
            int a = edge[0];
            int b = edge[1];
            to[a].push_back(b);
            to[b].push_back(a);
            hascycle =false;
            for(int i = 1 ; i<=visited.size(); i++) visited[i] = false;
             dfs(a,0);
             if(hascycle) return edge;
        }
       

      return {};

        
    }
    void dfs(int from , int pre){
        visited[from] = true ; 
        for(int go : to[from]){
            if(go == pre) continue;
            if(!visited[go]) dfs(go,from);
            else hascycle = true;
        }
    }
    vector<vector<int>> to;
    vector<bool> visited; 
    bool hascycle ;
};