LeetCode 947. Most Stones Removed with Same Row or Column

这道题本质就是 323. Number of Connected Components in an Undirected Graph。

 

DFS O(n^2)

一模一样, 只不过图要自己构建而已。

class Solution {
public:
    vector<list<int>> adj;
    
    int removeStones(vector<vector<int>>& stones) {
        int n=stones.size();
        adj.resize(n,list<int>());
        for (int i=0;i<n;++i){
            for (int j=i+1;j<n;++j){
                if (stones[i][0]==stones[j][0] || stones[i][1]==stones[j][1]){
                    adj[i].push_back(j);
                    adj[j].push_back(i);
                }
            }
        }
        int count=0;
        vector<bool> visited(n,false);
        for (int i=0;i<n;++i){
            if (!visited[i]){
                ++count;
                dfs(i,visited);
            }
        }
        return n-count;
    }
    
    void dfs(int i, vector<bool> &visited){
        if (visited[i]) return;
        visited[i] = true;
        for (auto x:adj[i]){
            dfs(x,visited);
        }
    }
};

 

Union Find O(n^2),两两union n^2

class Solution {
public:  
    vector<int> parent;

    int removeStones(vector<vector<int>>& stones) {
        int n=stones.size();
        parent.resize(n,-1);
        for (int i=0;i<n;++i){
            for (int j=i+1;j<n;++j){
                if (stones[i][0]==stones[j][0] || stones[i][1]==stones[j][1]){
                    Union(i,j);
                }
            }
        }
        int count=0;
        for (int x:parent){
            if (x<0) ++count;
        }
        return n-count;  
    }

    void Union(int x, int y){ // union by size
        int root1=Find(x), root2=Find(y);
        if (root1==root2) return;
        if (parent[root1]>parent[root2]){
            parent[root2] += parent[root1];
            parent[root1] = root2;
        }else{
            parent[root1] += parent[root2];
            parent[root2] = root1;
        }
    }
    
    int Find(int x){
        if (parent[x]<0) return x;
        return parent[x]=Find(parent[x]);
    }
};

 

Union Find (Optimized)

Solution里的很取巧的做法。横坐标纵坐标都一起union,这样只要遍历stones一次即可。这里将纵坐标+1000,就能简单区分横纵坐标。

时间复杂度 由于union by size,O(nlogn)。如果用union by rank来写,可以 O(n*α(n))。

class Solution {
public:   
    vector<int> parent;
    
    int removeStones(vector<vector<int>>& stones) {
        int n=stones.size();
        parent.resize(20000,-1);
        for (auto stone:stones){
            int x=stone[0], y=stone[1];
            Union(x,y+10000);
        }
        unordered_set<int> s;
        for (auto stone:stones){
            s.insert(Find(stone[0]));
        }
        return n-s.size();
        return 0;
    }
    
    void Union(int x, int y){ // union by size
        int root1=Find(x), root2=Find(y);
        if (root1==root2) return;
        if (parent[root1]>parent[root2]){
            parent[root2] += parent[root1];
            parent[root1] = root2;
        }else{
            parent[root1] += parent[root2];
            parent[root2] = root1;
        }
    }
    
    int Find(int x){
        if (parent[x]<0) return x;
        return parent[x]=Find(parent[x]);
    }
};

 

posted @ 2019-06-06 13:58  約束の空  阅读(299)  评论(0)    收藏  举报