无向图的连通三元组最小度数问题

题目描述:

        给你一个无向图,整数 n 表示图中节点的数目,edges 数组表示图中的边,其中 edges[i] = [ui, vi] ,表示 ui 和 vi 之间有一条无向边。

        一个 连通三元组 指的是 三个 节点组成的集合且这三个点之间 两两 有边。

        连通三元组的度数 是所有满足此条件的边的数目:一个顶点在这个三元组内,而另一个顶点不在这个三元组内。

        请你返回所有连通三元组中度数的 最小值 ,如果图中没有连通三元组,那么返回 -1 。

示例与输入:

输入:n = 6, edges = [[1,2],[1,3],[3,2],[4,1],[5,2],[3,6]]
输出:3
解释:图中连通三元组为1-2-3,该连通三元组的度数为边:1-4,2-5,3-6,故该三元组度数为3。由于图中不存在其它三元组,所以该无向图的最小度数为3。 
解题思路:

        我们容易根据edges计算出每个节点的连接边数量,只需遍历一遍edges即可。图中的点、边关系可列为下表:

节点该节点连接其它节点
node-12,3,4
node-21,3,5
node-31,2,6
node-41
node-52
node-63

        如果知道(1,2,3)三个点构成三元组,那么节点1的度数就是节点1连接的边的数量减2。以此类推,可以知道节点2的度数,节点3的度数,三个节点度数之和就是该三元组的度数。

        所以,已知一个三元组,怎么求其度数弄清楚之后,接下来的任务就是求出所有三元组。这里的方法类似于DFS。创建一个栈stack,stack内放入一个节点 i 的所有连接结点;随后,该stack内的节点依次弹出,每弹出一个节点 j ,就寻找该弹出节点所连接的所有节点,放进一个list中。比对list和stack的剩余元素是否存在交集,如果有交集并记为k,则 i , j , k就构成一个三元组。

        接下来只要寻找到三元组中度数的最小值即可。

代码--python3:

class Solution:
    def minTrioDegree(self, n: int, edges: list) -> int:
        edges_dict = {}
        for i in edges:    # 创建一个字典,遍历edges,把每个节点连接的节点以list结构记下
            edges_dict.setdefault(i[0], list()).append(i[1])
            edges_dict.setdefault(i[1], list()).append(i[0])
        # access_node记录访问过的节点,避免重复找三元组
        tri_degree, access_node = [], set()
        for i in edges_dict:
            # 调用edges_dict中的value,但不想改变原数据(后面用于求度数),用一次深拷贝
            stack = set(copy.deepcopy(edges_dict[i])).difference(access_node)    # 去重
            if len(stack) <= 1:    # 一个节点若连接的节点都不够两个就别凑热闹了,肯定构不成三元
                continue
            access_node.add(i)
            while stack:
                a = stack.pop()
                b = set(edges_dict[a]).intersection(set(stack)) # set求交集,空间换时间
                if b:
                    for k in b:
                        tri_degree.append((i,a,k))
        ans = -1
        for i in tri_degree:    # 求度数
            temp = len(edges_dict[i[0]])+len(edges_dict[i[1]])+len(edges_dict[i[2]])-6
            if ans == -1:
                ans = temp
            else:
                ans = min(ans, temp)
        return ans

改进:

1.  set是很方便,但其底层去重实际用的是红黑树,并且set会改变原list中的顺序。其高效的同时空间复杂度会比遍历要高很多。

2.  如果需要频繁查询,而非增、删、改,可以使用哈希表,增加效率(近似看作较大的O(1))。当然哈希表创建的过程要比array、linklist等结构时间更多。根据需求采用不同的数据结构。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值