【LeetCode】1584 and 144(Kruskal 最⼩⽣成树算法)

最小生成树

一、什么是最小生成树?
「树」和「图」最大的区别就是树不会包含环,而图可以包含环。换句话说,树就是「无环连通图」。
那么什么是图的「⽣成树」呢,其实按字⾯意思也好理解,就是在图中找⼀棵包含图中的所有节点的树。专业点说,⽣成树是含有图中所有顶点的「⽆环连通⼦图」。
容易想到,⼀幅图可以有很多不同的⽣成树,⽐如下⾯这幅图,红⾊的边就组成了两棵不同的⽣成树:
在这里插入图片描述
对于加权图,每条边都有权重,所以每棵⽣成树都有⼀个权重和。⽐如上图,右侧⽣成树的权重和显然⽐左侧⽣成树的权重和要⼩。
那么最⼩⽣成树很好理解了,所有可能的⽣成树中,权重和最⼩的那棵⽣成树就叫「最⼩⽣成树」。
二、Kruskal算法
所谓最⼩⽣成树,就是图中若⼲边的集合(我们后⽂称这个集合为 mst,最⼩⽣成树的英⽂缩写),你要保证这些边:
1、包含图中的所有节点。
2、形成的结构是树结构(即不存在环)。
3、权重和最⼩。
前两条其实可以很容易地利⽤ Union-Find 算法做到。对于第三点,如何保证得到的生成树是权重和最小的,这里使用到了贪心思路。将所有边按照权重从小到大排序,从权重最小的边开始遍历,如果这条边和mst中的其它边不会形成环,则这条边是最小生成树的一部分,将它加入mst集合;否则,这条边不是最小生成树的一部分,不要把它加入mst集合。这样,最后mst集合中的边就形成了最小生成树,下面我们看一道例题来运用一下 Kruskal 算法。

1584. 连接所有点的最小费用

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
解法:Kruskal 算法

class UF:
    def __init__(self, n):
        self.n = n
        self.size = [1] * n
        self.parents = list(range(n))
    
    def find(self, x: int) -> int:
        while x != self.parents[x]:
            self.parents[x] = self.parents[self.parents[x]]
            x = self.parents[x]
        return x
    
    def unionSet(self, x: int, y: int) -> bool:
        fx, fy = self.find(x), self.find(y)
        if fx == fy:
            return False

        if self.size[fx] < self.size[fy]:
            fx, fy = fy, fx
        
        self.size[fx] += self.size[fy]
        self.parents[fy] = fx
        return True

    def connected(self, p, q):
        return self.find(p) == self.find(q)

class Solution:
    def minCostConnectPoints(self, points: List[List[int]]) -> int:
    	# 距离计算函数
        dist = lambda x, y: abs(points[x][0] - points[y][0]) 
        + abs(points[x][1] - points[y][1])
        n = len(points)
        # 并查集
        dsu = UF(n)
        edges = list()

        for i in range(n):
            for j in range(i + 1, n):
                edges.append((dist(i, j), i, j))
        # 按距离大小从小到大排序
        edges.sort()
        ret, num = 0, 1
        for length, x, y in edges:
        	# 当前边加入会存在环,舍弃
            if dsu.connected(x, y):
                continue
            
            ret += length
            # 添加该边,更新并查集信息
            dsu.unionSet(x, y)
			# 节点数量等于n,则符合条件,可提前退出
            num += 1
            if num == n:
                break
        
        return ret

144. 二叉树的前序遍历

在这里插入图片描述
在这里插入图片描述
解法:DFS
这里使用之前文章所介绍的二叉树前序遍历框架即可。

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        def preorder(root: TreeNode):
            if not root:
                return
            res.append(root.val)
            preorder(root.left)
            preorder(root.right)
        
        res = list()
        preorder(root)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值