并查集算法练习(不定时更新)

本文介绍了四道LeetCode上的编程题目,包括找寻未排序数组中的最长连续序列、填充矩阵中被X包围的O、计算二维数组中最大岛屿面积以及确定省份数量。解题方法涉及哈希表、深度优先搜索(DFS)和DisjointSetUnion数据结构的应用。
摘要由CSDN通过智能技术生成

第一题

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-consecutive-sequence
 

public:
    int longestConsecutive(vector<int>& nums) {

        unordered_set<int> unique_set;
        for(const int& e:nums)
        {
            unique_set.insert(e);
        }
        int max_ret=0;

        for(const int& e:nums){
            if(unique_set.count(e-1)==0){
                int tmp_ret=1;
                int next_find=e+1;
                while(unique_set.count(next_find)){
                    ++tmp_ret;
                    ++next_find;
                }
                max_ret=max(tmp_ret,max_ret);
            }
        }

        return max_ret;
    }

    //     int longestConsecutive(vector<int>& nums) {
    //     unordered_set<int> num_set;
    //     for (const int& num : nums) {
    //         num_set.insert(num);
    //     }

    //     int longestStreak = 0;

    //     for (const int& num : num_set) {
    //         if (!num_set.count(num - 1)) {
    //             int currentNum = num;
    //             int currentStreak = 1;

    //             while (num_set.count(currentNum + 1)) {
    //                 currentNum += 1;
    //                 currentStreak += 1;
    //             }

    //             longestStreak = max(longestStreak, currentStreak);
    //         }
    //     }

    //     return longestStreak;           
    // }


};

第二题

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

不被围住的区域一定与边界相通。

class Solution {
public:
int n,m;
void dfs(vector<vector<char>>& board,int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m&&board[x][y]=='O'){
        board[x][y]='Q';
        dfs(board,x,y-1);
        dfs(board,x,y+1);
        dfs(board,x-1,y);
        dfs(board,x+1,y);
    }//如果区域合法,对矩阵进行访问
    else{
        return;
    }
}
    void solve(vector<vector<char>>& board) {
        n=board.size();
        if(n==0)
        {
            return;
        }

        m=board[0].size();

        for(int i=0;i<n;i++){
            dfs(board,i,0);
            dfs(board,i,m-1);
        }

        for(int j=0;j<m;j++){
            dfs(board,0,j);
            dfs(board,n-1,j);
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]=='Q'){
                    board[i][j]='O';
                }
                else if(board[i][j]=='O'){
                    board[i][j]='X';
                }
            }
        }
    }
};

第三题

给定一个由 0 和 1 组成的非空二维数组 grid ,用来表示海洋岛屿地图。

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

class Solution {
public:
//为了防止我们对一个岛屿的面积进行重复统计,将访问过的地区置为2,再恢复
int m;
int n;
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m=grid.size();
        n=grid[0].size();
        int max_ret=0;
        for(int x1=0;x1<m;++x1){
            for(int y1=0;y1<n;++y1){
                if(grid[x1][y1]==1){
                int ret=0;
                dfs(grid,x1,y1,ret);
                max_ret=max(max_ret,ret);
                }

            }
        }
        cout<<max_ret;
        return max_ret;
    }

    void dfs(vector<vector<int>>& grid,const int& x,const int& y,int& ret){
        if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==1){
            grid[x][y]=2;
            ++ret;
            dfs(grid,x-1,y,ret);
            dfs(grid,x+1,y,ret);
            dfs(grid,x,y-1,ret);
            dfs(grid,x,y+1,ret);
        }
        else{
            return;
        }
    }
};

第四题 省份数量

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/bLyHh0
 

class Disjoint_Set_Union {
	public:
	Disjoint_Set_Union(int n = 10)
		:_dsu(n, -1)
	{

	}
	int find_root(int k)//寻找该元素的祖先
	{
		while (_dsu[k]>=0)
		{
			k= _dsu[k];
		}
		//得到的必然是正数,因为个数作为负数不进去
		return k;
	}
	void Union(int x, int y)//合并两个集合
	{
		x = find_root(x);
		y = find_root(y);

		if (x > y)
			swap(x, y);//把下标小的作为新根

		if (x != y)
		{
			_dsu[x] += _dsu[y];
			_dsu[y] = x;
		}
	}

	bool in_set(int x, int y) {
		x = find_root(x);
		y = find_root(y);
		if (x == y)
			return true;
		return false;
	}

	int set_size()
	{
		int total = 0;
		for (int i = 0; i < _dsu.size(); ++i) {
			if (_dsu[i] < 0) {
				++total;
			}
		}
		return total;
	}
private:
	vector<int>  _dsu;//记录元素的祖先

};

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        Disjoint_Set_Union dsu(isConnected.size());
        for(int i=0;i<isConnected.size();++i){
            for(int j=0;j<isConnected[i].size();++j){
                if(isConnected[i][j]==1){
                    dsu.Union(i,j);
                }
            }
        }

        return dsu.set_size();
    }
};

第五题,等式方程的可满足性

class Disjoint_Set_Union {

    public:

    Disjoint_Set_Union(int n = 10)

        :_dsu(n, -1)

    {



    }

    int find_root(int k)//寻找该元素的祖先

    {

        while (_dsu[k]>=0)

        {

            k= _dsu[k];

        }

        //得到的必然是正数,因为个数作为负数不进去

        return k;

    }

    void Union(int x, int y)//合并两个集合

    {

        x = find_root(x);

        y = find_root(y);



        if (x > y)

            swap(x, y);//把下标小的作为新根



        if (x != y)

        {

            _dsu[x] += _dsu[y];

            _dsu[y] = x;

        }

    }



    bool in_set(int x, int y) {

        x = find_root(x);

        y = find_root(y);

        if (x == y)

            return true;

        return false;

    }



    int set_size()

    {

        int total = 0;

        for (int i = 0; i < _dsu.size(); ++i) {

            if (_dsu[i] < 0) {

                ++total;

            }

        }

        return total;

    }

private:

    vector<int>  _dsu;//记录元素的祖先



};

class Solution {

public:

    bool equationsPossible(vector<string>& equations) {

        Disjoint_Set_Union dsu(26);



        for(int i=0;i<equations.size();++i){

            char x=equations[i][0];

            char y=equations[i][3];

            char flag=equations[i][1];



            if(flag=='='){

                dsu.Union(x-'a',y-'a');

            }



            else{

                if(dsu.in_set(x-'a',y-'a')==true){

                    return false;

                }

            }

        }

        for(int i=0;i<equations.size();++i){

            char x=equations[i][0];

            char y=equations[i][3];

            char flag=equations[i][1];



            if(flag=='!'){

                if(dsu.in_set(x-'a',y-'a')==true){

                return false;

                }

            }

        }

        return true;

    }

};

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脆皮骷髏人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值