Leetcode 261 Graph Valid Tree

终于开始写技术博客啦,之前一直想要尝试但是由于太懒,刷题的顺序比较随意,刷题之后也没有总结,现在终于开始认真的按照Tag刷题啦,所以开始写第一篇技术博客啦: )

首先把题目抄一下:

Given n nodes labeled from 0 to n-1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.
Example1:

Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]]
Output: true

Example2:

Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
Output: false

Note: you can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0,1] is the same as [1,0] and thus will not appear together in edges.

这个题目被Leetcode划分到了Union-Find, Graph, BFS,以及DFS这几个标签下,我是在Graph的标签底下刷到的。

题目分析与转化

那么首先来分析一波,其实这个题目作为一个图的题目来看,因为返回的是bool型数据,那吗判断结果为true的等价条件是

  1. (1)边数=n-1
    (2)连通分支的数量为1
    (3)连通分支内没有环

  2. (1)边数=n-1
    (2)连通分支数量为1

这两个都是等价条件,但显然第1个条件更复杂,多了一个条件。这是为啥,因为1中的(3)其实可以从(1)(2)推出。(3)其实是冗余的。

具体实现思路

1. DFS

首先图的题目我是比较偏向于dfs的,那么第一版本的我的代码就是用dfs实现的,而且我选的等价条件是第1个,其实有点绕。

1.1 等价条件1
class Solution {
public:
   bool dfs(int i,int pre,vector<bool>& visited ,vector<vector<int>>& graph){
       if(visited[i])return false;
       visited[i]=true;
       for(auto child: graph[i]){
           if(child!=pre){
               if(!dfs(child, i, visited, graph))return false;
           }
       }
       return true;
   }
   bool validTree(int n, vector<vector<int>>& edges) {
       if(edges.size()!=n-1)return false;
       vector<bool> visited(n,false);
       vector<vector<int>> graph(n,vector<int>());
       for(auto vec: edges){
           graph[vec[0]].push_back(vec[1]);
           graph[vec[1]].push_back(vec[0]);
       }
       if(dfs(0,-1, visited, graph)==false)return false;
       for(auto i:visited){
           if(i==false)return false;
       }
       return true;
   }
};

因为我用的等价条件1,所以还要涉及处理无向图中是否有环的问题(这其实没必要而且挺麻烦的,但是我一开始没有想到最简洁的等价转化方法)。
那么连通的无向图,无环则是树,有环则在dfs过程中出现重复访问的节点,需要注意的是,因为是无向图,所以dfs的时候需要把父节点排除筛查范围。

1.2 等价条件2
class Solution {
public:
    void dfs(int i,vector<bool>& visited ,vector<vector<int>>& graph){
        if(visited[i])return;
        visited[i]=true;
        for(auto child: graph[i]){
            dfs(child, visited, graph);
        }
    }
    bool validTree(int n, vector<vector<int>>& edges) {
        if(edges.size()!=n-1)return false;
        vector<bool> visited(n,false);
        vector<vector<int>> graph(n,vector<int>());
        for(auto vec: edges){
            graph[vec[0]].push_back(vec[1]);
            graph[vec[1]].push_back(vec[0]);
        }
        dfs(0,visited, graph);
        for(auto i:visited){
            if(i==false)return false;
        }
        return true;
    }
};

从代码中可以看出仅仅在dfs函数中有细微的差别。条件1更加简介,只是遍历连通分支,并不在意是否有环。

2. Union_Find

这个方法以为我一开始转化的时候转化的繁了所以并没有想到,但是这个方法其实非常直观。本来union_find就常用来判断连通分支数目。

class UnionFind{
    vector<int> vec;
    int count;
    public: UnionFind(int n){
        vec= vector<int>(n,0);
        for(int i=0;i<n;i++){
            vec[i]=i;
        }
        count=n;
    }
    public: void union_(int a, int b){
        int RA = find(a);
        int RB = find(b);
        if(RA==RB)return;
        else {
            vec[RA]=RB;
            count--;
        }

    }
    public: int find(int a){
        while(vec[a]!=a){
            vec[a]=vec[vec[a]];
            a=vec[a];
        }
        return a;
    }
    public: int getCount(){
        return count;
    }
};
class Solution {
public:
    bool validTree(int n, vector<vector<int>>& edges) {
        if(edges.size()!=n-1)return false;
        UnionFind uf(n);
        for(auto edge:edges){
            uf.union_(edge[0], edge[1]);
        }
        return uf.getCount()==1;
    }
};

union-find的时候要注意,为了减少时间复杂度,可以选择在find的时候减少树的高度。

OKK完结撒花!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,272评论 0 3
  • Remove time complexity: remove from a set is O(1), remove...
    云端漫步_b5aa阅读 627评论 0 0
  • 四种重要的图模型: 无向图(简单连接) 有向图(连接有方向性) 加权图(连接带有权值) 加权有向图(连接既有方向性...
    算法手记阅读 335评论 0 0
  • Graph的题: 值得思考的点和概念:树、有向图、无向图、相连性、有圈无圈树是各节点之间只有一条路可走的无圈无向图...
    __小赤佬__阅读 588评论 0 0
  • 原题 给出 n 个节点,标号分别从 0 到 n - 1 并且给出一个 无向 边的列表 (给出每条边的两个顶点), ...
    Jason_Yuan阅读 1,116评论 1 0