[英雄星球六月集训LeetCode解题日报] 第21日 堆

日报

  • 只有第四题用了堆。

题目

一、 2285. 道路的最大总重要性

链接: 2285. 道路的最大总重要性

1. 题目描述

给你一个整数 n ,表示一个国家里的城市数目。城市编号为 0 到 n - 1 。

给你一个二维整数数组 roads ,其中 roads[i] = [ai, bi] 表示城市 ai 和 bi 之间有一条 双向 道路。

你需要给每个城市安排一个从 1 到 n 之间的整数值,且每个值只能被使用 一次 。道路的 重要性 定义为这条道路连接的两座城市数值 之和 。

请你返回在最优安排下,所有道路重要性 之和 最大 为多少。

2. 思路分析

给每个城市计数,出现次数多的给大值。

3. 代码实现
class Solution:
    def maximumImportance(self, n: int, roads: List[List[int]]) -> int:
        cnt = [0]*n
        for a,b in roads:
            cnt[a] += 1
            cnt[b] += 1
        cnt.sort()
        return sum(k*v for k,v in enumerate(cnt,1))

二、 675. 为高尔夫比赛砍树

链接: 675. 为高尔夫比赛砍树

1. 题目描述

在这里插入图片描述

2. 思路分析
  • 这题之前做过,用朴素BFS、优先队列BFS、A*都可以,甚至可以并查集预处理失败的情况(所有树连通)。
  • 这几天刚学的双向BFS,我要写双向!
3. 代码实现
class Solution:
    def cutOffTree(self, forest: List[List[int]]) -> int:
        trees = [(0,(0,0))]  # 从0出发
        m,n = len(forest),len(forest[0])
        if forest[0][0] == 0:
            return -1
        road = set()
        for i in range(m):
            for j in range(n):                    
                if forest[i][j] > 0:                    
                    road.add((i,j))
                if forest[i][j] > 1:
                    trees.append((forest[i][j],(i,j)))
        trees.sort()
        dirs = [(1,0),(-1,0),(0,1),(0,-1)]

        def bfs(start,end):
            if start == end:
                return 0            
            v1 = {start:0}
            v2 = {end:0}
            q1 = deque(v1)
            q2 = deque(v2)
            def debfs(q,v1,v2):
                step = v1[q[0]]+1
                for _ in range(len(q)):
                    i,j = q.popleft()
                    for dx,dy in dirs:
                        nxt = (i+dx,j+dy)
                        if nxt in v2:
                            return step + v2[nxt]
                        if nxt in road and nxt not in v1:
                            v1[nxt] = step
                            q.append(nxt)
                return -1  

            step = 0
            while q1 and q2:
                ret = debfs(q1,v1,v2) if len(q1)>len(q2) else debfs(q2,v2,v1)
                if ret != -1:
                    return ret
            return -1                    

        ans = 0
        for i in range(1,len(trees)):
            ret = bfs(trees[i-1][1],trees[i][1])
            if ret == -1:
                return -1
            ans += ret
        return ans

三、 1405. 最长快乐字符串

链接: 1405. 最长快乐字符串

1. 题目描述

在这里插入图片描述

2. 思路分析
  • 用一个数组记录剩余的字母数量,并且降序。
  • 每次尝试拿前两种字符c1,c2用,c1用2个,c2用1个或2个,取决当前于c2的数量是否依然小于c1。
  • 因为如果c2比c1少,再拿的多,后边就有c1不能找到分割字符了。
3. 代码实现
class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        pool = [(a,'a'),(b,'b'),(c,'c')]
        pool.sort(reverse=True)
        ans = ''
        while True:
            cnta,a = pool[0] 
            cnta = min(2,cnta)
            ans += a*cnta 
            pool[0] = (pool[0][0]-cnta,a)
            cntb,b = pool[1]
            if cntb == 0:
                break
            cntb = min(1 if cntb < pool[0][0] else 2 ,cntb)
            ans += b * cntb
            pool[1] = (pool[1][0]-cntb,b)
            pool.sort(reverse=True)
        return ans

四、 659. 分割数组为连续子序列

链接: 659. 分割数组为连续子序列

1. 题目描述

在这里插入图片描述

2. 思路分析

蜘蛛纸牌思路。

  • 把每个数放到一个队伍里。
  • 所有队伍放到一个优先队列里维护,(队尾数字,长度)。
  • 因为是升序,因此新来的数一定可以追加到某个队伍队尾,不可能是队中或队首。
  • 如果数字a没有队伍可以进,一定是没有看见a-1这个数。
  • 开始讨论当前所有队伍情况:
  • 那么如果队伍里还存在a-2,这个队就是没用的了,以后再也不存在能进来的数字,判断一下长度,移除所有这种队伍,如果长度<3,返回False。
  • 然后现在堆顶的队尾一定是a或a-1,
  • 队尾==a-1就追加进这个队伍;
  • 队尾==a就把a单独开一个队伍。
3. 代码实现
class Solution:
    def isPossible(self, nums: List[int]) -> bool:
        n = len(nums)
        if n < 3:
            return False
        q = []  # 优先队列储存每个牌队的最后一个数和长度
        for a in nums:
            while q and q[0][0] +1<a:  # 把所有队尾元素小于a-1的队干掉,判断长度。因为后边不会有数追到它后边。
                top,d = heapq.heappop(q)
                if d<3:
                    return False
            if not q:  # 堆没了就加一个
                q.append((a,1))                 
            else:   # 现在堆顶的队,队尾一定是a或a-1
                top,d = q[0]
                if top == a:  # 最小队尾==这个数,不能追加把这个数放新的队
                    heapq.heappush(q,(a,1))
                elif top + 1 == a:  # 可以追加到最短队,那就追加
                    heapq.heapreplace(q,(a,d+1))
        # print(q)
        return all(d >= 3 for top,d in q)

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值