LeetCode:1627. 带阈值的图连通性

每日一题,并查集+暴力yyds!

题目链接:1627. 带阈值的图连通性 - 力扣(LeetCode)

题目信息:

有 n 座城市,编号从 1 到 n 。编号为 x 和 y 的两座城市直接连通的前提是: x 和 y 的公因数中,至少有一个 严格大于 某个阈值 threshold 。更正式地说,如果存在整数 z ,且满足以下所有条件,则编号 x 和 y 的城市之间有一条道路:

1.x % z == 0

2.y % z == 0

3.z > threshold

给你两个整数 n 和 threshold ,以及一个待查询数组,请你判断每个查询 queries[i] = [ai, bi] 指向的城市 ai 和 bi 是否连通(即,它们之间是否存在一条路径)。

返回数组 answer ,其中answer.length == queries.length 。如果第 i 个查询中指向的城市 ai 和 bi 连通,则 answer[i] 为 true ;如果不连通,则 answer[i] 为 false 。

题目解析:

给定n个城市,城市代码分别为1、2、3...n;若两城市间代码符合一个条件【城市代码的最大公因数大于threshold】则能连通,城市间可通过另一个城市进行连通再给定一个城市代码数组queries(其中两两一组),返回一个List<Boolean>数组(其中的值为queries中一组城市之间是否连通)

解题方法:并查集+(暴力||手动筛选)

代码及超详细解析:

方法一:暴力yyds:

class Solution {
    static int[]fa;//定义一个数组存储所有城市代码的根城市代码,第i个fa[i]表示第i个城市与第fa[i]连通
    public List<Boolean> areConnected(int n, int threshold, int[][] queries) {
        fa=new int[n+1];
        for(int i=1;i<=n;i++)fa[i]=i;//初始化所有城市代码,使其根城市代码最开始指向自身
        List<Boolean> answer=new ArrayList<>();//创建返回的List<boolean>
//此处与方法二不同,暴力太香了
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j+=i)
            {
                if(getCommonFactor(i,j)>threshold)merge(i,j);
            }
        }
// 
        //判断给定城市代码数组中一组城市是否连通
        for(int[]q:queries)//使用增强for
        {
            if(find(q[0])==find(q[1]))answer.add(true);//两城市代码的根城市代码是否相同
            else answer.add(false);
        }
        return answer;
    }

//查找x城市代码的根城市代码
    public int find(int x)
    {
        if(fa[x]==x)return x;//如果是他本身则返回自身
        fa[x]=find(fa[x]);//压缩路径:find目的是查找根城市,将根城市代码赋给x城市,表示x城市与根城市连通
        return fa[x];//返回根城市代码,用于比较
    }

//连通两个城市的根城市
    public void merge(int i,int j)
    {
        fa[find(i)]=find(j);//将i城市的根城市的根代码改成j城市的根城市代码
    }
//返回两数字最大公因数
    public int getCommonFactor(int a,int b)
    {
        int c=a%b;
        while(c!=0)
        {
            a=b;
            b=c;
            c=a%b;
        }
        return b;
    }
//
}

方法二:手动过滤不符合条件的城市代码,节省时间

class Solution {
    static int[]fa;//定义一个数组存储所有城市代码的根城市代码,第i个fa[i]表示第i个城市与第fa[i]连通
    public List<Boolean> areConnected(int n, int threshold, int[][] queries) {
        fa=new int[n+1];
        for(int i=1;i<=n;i++)fa[i]=i;//初始化所有城市代码,使其根城市代码最开始指向自身
        List<Boolean> answer=new ArrayList<>();//创建返回的List<boolean>
    //【此处分析忽略threshold=0的情况】人工过滤不符合条件的城市代码,从而节省时间
        //i不从0、1开始,j不从0、1、i、i~2i-1开始。
        //i的初始值为threshold+1,因为小于他的城市代码不跟任何城市连通
        //j若从2i之前开始,(i,j)最大公因数为1,不符合threshold>1的情况
        //j增量为i:先找出与i直接连通的城市,若两城市间接连通则两个城市根城市代码一定相同
        for(int i=threshold+1;i<=n;i++)
        {
            for(int j=i*i;j<=n;j+=i)
            merge(i,j);/连通两个城市的根城市代码
        }      
        //判断给定城市代码数组中一组城市是否连通
        for(int[]q:queries)//使用增强for
        {
            if(find(q[0])==find(q[1]))answer.add(true);//两城市代码的根城市代码是否相同
            else answer.add(false);
        }
        return answer;
    }

//查找x城市代码的根城市代码
    public int find(int x)
    {
        if(fa[x]==x)return x;//如果是他本身则返回自身
        fa[x]=find(fa[x]);//压缩路径:find目的是查找根城市,将根城市代码赋给x城市,表示x城市与根城市连通
        return fa[x];//返回根城市代码,用于比较
    }

//连通两个城市的根城市
    public void merge(int i,int j)
    {
        fa[find(i)]=find(j);//将i城市的根城市的根代码改成j城市的根城市代码
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值