Python每日一练:蚂蚁家族(详解集合法)


前言

这题挺有意思,感觉评简单难度有点低了,如果正经用无向图来做,代码还是有点长的。首先得建立节点,估计除第一个和最后一个每个节点都是一条线连进,一条线连出的。就可以这样设计节点,然后生成树,最后深度搜索。既然都是简单评价了,咱就用个简单的解法。这题和有一道参加宴会介绍人认识的题目很像,都可以用集合来解,而且更容易让人理解。

在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、题目

题目描述:
小蚂蚁群是一个庞大的群体,在这个蚂蚁群中有n只小蚂蚁 ,为了保证所有蚂蚁在消息传送的时候都能接收到消息,需要在他们之间建立通信关系。就是要求小蚂蚁都可以通过多只或者直接联系到其他人。 已知几条小蚂蚁之间有通信关系,请问还需要再新建至少多少条关系?

输入描述:
第一行输入整数n,m;n为小蚂蚁总数;m为关系数。(1<=n,m<=1000) 以下m行每行m对整数x,y。(代表x与y有联系)

输出描述:
输出最少需要新建关系数。

二、代码分析

代码如下(示例):

    def solution(self, n, m, vector):
        result = None
        # TODO: 请在此编写代码
        if vector.__len__() == 0:
            return n-1
        relation = [set(vector[0])]   # 用于存放有联系的集合
        rl = 1              # 上面集合的长度,手动写会快些,本身也是可知的
        for x in vector:    # 查找联系,生成集合
            setx = set(x)
            for j in range(rl):
                if ( not relation[j].isdisjoint(setx) ):
                    relation[j] = relation[j].union(setx)
                    break
                elif j== rl-1:
                    relation.append(setx)
                    rl += 1
        part = relation.__len__()-  # 团体间无联系的数量,-1是需要几个新建的联系
        rela_all = set()    # 所有已参加团体的蚂蚁
        for x in relation:
            rela_all = rela_all.union(x)
        rela_all = len(rela_all)
        result = part +  n - rela_all  
        return result

看注释也就明白了,很简单的逻辑:
1、如果关系列表是空的,则需要新建n-1个关系。嗯,偷偷告诉你们,有这样的数据690,0,[ ]。

2、默认第一个关系为一个小团体的初始,设置rl = 1,因为所有新增小团体都是下面代码生成的,是可知的,所以此处写死了团体数量。下面的循环有相应的代码来增加这个值,很明显题目是要求无向图的,咱写集合肯定得考虑效率问题。事实上不用集合,直接用列表查询会超时,别问我咋知道的…

3、稍微有点复杂的就是关系集合生成这一步了,代码中x是每对关系,先变成集合。然后去列表中的小团体集合查询,有就加入,没有就新建一个小团体。其中 isdisjoint 是判断是否交集,这是个否定判断。意思是:“是不是不是交集” 呃~ 这要晕的,换个说法 “是否非交集”。返回 True 表示的是:不是交集。所以笔者在这里加了not,当是交集的时候,就加入。下面的else,要判断是不是最后一个小团体。因为 ralation 列表中可能有很多小团体集合,所以每次要遍历。只有当是最后一个小团体了,上面的代码又没将 x 加入,才新建一个小团体,同时将列表长度 rl 加1。

4、如上,我们就得到了所有的小团体,这里用 part 变量表示。显然,小团体之间需要一个联系就够了,所以这里是小团体数减1。

5、再然后,我们需要知道所有已加入小团体的蚂蚁数。这里用了一个 for 循环。全加入到一个集合中,union 是并集运算。

6、最后小团体之间需要的联系数加上蚂蚁数减去已参加小团体的数就是答案了。


总结

本想再用无向图搜索解一遍的,偷懒了~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无证的攻城狮

如本文对您有用,大爷给打个赏!

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

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

打赏作者

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

抵扣说明:

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

余额充值