LeetCode 1615. 最大网络秩 / 2389. 和有限的最长子序列 / 1626. 无矛盾的最佳球队(排序+动态规划)

1615. 最大网络秩

2023.3.15 每日一题

题目描述

n 座城市和一些连接这些城市的道路 roads 共同组成一个基础设施网络。每个 roads[i] = [ai, bi] 都表示在城市 ai 和 bi 之间有一条双向道路。

两座不同城市构成的 城市对 的 网络秩 定义为:与这两座城市 直接 相连的道路总数。如果存在一条道路直接连接这两座城市,则这条道路只计算 一次 。

整个基础设施网络的 最大网络秩 是所有不同城市对中的 最大网络秩 。

给你整数 n 和数组 roads,返回整个基础设施网络的 最大网络秩 。

示例 1:

在这里插入图片描述
输入:n = 4, roads = [[0,1],[0,3],[1,2],[1,3]]
输出:4
解释:城市 0 和 1 的网络秩是 4,因为共有 4 条道路与城市 0 或 1 相连。位于 0 和 1 之间的道路只计算一次。

示例 2:

在这里插入图片描述
输入:n = 5, roads = [[0,1],[0,3],[1,2],[1,3],[2,3],[2,4]]
输出:5
解释:共有 5 条道路与城市 1 或 2 相连。

示例 3:

输入:n = 8, roads = [[0,1],[1,2],[2,3],[2,4],[5,6],[5,7]]
输出:5
解释:2 和 5 的网络秩为 5,注意并非所有的城市都需要连接起来。

提示:

2 <= n <= 100
0 <= roads.length <= n * (n - 1) / 2
roads[i].length == 2
0 <= ai, bi <= n-1
ai != bi
每对城市之间 最多只有一条 道路相连

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximal-network-rank
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

其实思路还是挺简单的,就是写的有点麻烦,看下题解怎么写的
我这里写判断两个城市是否相连的这个步骤可以参考题解里的方法,在前面创建一个boolean数组,用来存储两个城市之间是否有直连,那么在后面判断city1和city2中两个城市是否相连的过程,就可以直接计算,降低复杂度

class Solution:
    def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int:
        # 统计每个城市直连的道路个数,然后将两个最多的找出来
        # 两个城市之间的道路最多有一条是重复的
        # 所以找的时候要找道路最多的一个城市,如果有和这个数量相同的城市,
        # 那么就找这些城市有没有不相连的,如果有,就是2MAX,否则就是2max-1

        # 如果第二个道路多的城市是与第一个城市道路不一样的,那么第一个城市是固定的,第二个是可选择的

        count = [0] * n
        for a,b in roads:
            count[a] += 1
            count[b] += 1
        
        max1 = 0
        max2 = 0

        # 挑选出最多的两个城市
        for i, x in enumerate(count):
            if x > max1:
                max2 = max1
                max1 = x
            elif x > max2:
                max2 = x
        
        city1 = []
        city2 = []
        for i, x in enumerate(count):
            if x == max1:
                city1.append(i)
            if x == max2:
                city2.append(i)
        
        #print(city1)
        #print(city2)
        c = 0
        for a,b in roads:
            if (a in city1 and b in city2) or (a in city2 and b in city1):
                c += 1
        
        #print(c)
        # 如果两个城市道路数相同,那么就看有没有不连接的
        # 如果这两个城市连接数等于所给的连接数,那么就说明这些城市都互联,那么就是max*2-1
        if max1 == max2:
            if (len(city1) - 1) * len(city2) / 2 == c:
                return max1 * 2 - 1
            else:
                return max1 * 2
        else:
            if (len(city1) + 1) * len(city2) / 2 == c:
                return max1 + max2 - 1
            else:
                return max1 + max2

2389. 和有限的最长子序列

2023.3.17 每日一题

题目描述

给你一个长度为 n 的整数数组 nums ,和一个长度为 m 的整数数组 queries 。

返回一个长度为 m 的数组 answer ,其中 answer[i] 是 nums 中 元素之和小于等于 queries[i] 的 子序列 的 最大 长度 。

子序列 是由一个数组删除某些元素(也可以不删除)但不改变剩余元素顺序得到的一个数组。

示例 1:

输入:nums = [4,5,2,1], queries = [3,10,21]
输出:[2,3,4]
解释:queries 对应的 answer 如下:
-子序列 [2,1] 的和小于或等于 3 。可以证明满足题目要求的子序列的最大长度是 2 ,所以 answer[0] = 2 。
-子序列 [4,5,1] 的和小于或等于 10 。可以证明满足题目要求的子序列的最大长度是 3 ,所以 answer[1] = 3 。
-子序列 [4,5,2,1] 的和小于或等于 21 。可以证明满足题目要求的子序列的最大长度是 4 ,所以 answer[2] = 4 。

示例 2:

输入:nums = [2,3,4,5], queries = [1]
输出:[0]
解释:空子序列是唯一一个满足元素和小于或等于 1 的子序列,所以 answer[0] = 0 。

提示:

n == nums.length
m == queries.length
1 <= n, m <= 1000
1 <= nums[i], queries[i] <= 10^6

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-subsequence-with-limited-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

先写了个这个思路的代码1,但是发现有错,但是又不知道哪里有错。
后面找了半天发现是如果查询有相同的话,就会覆盖掉
所以还是得前缀和加二分

class Solution {
    public int[] answerQueries(int[] nums, int[] queries) {
        int m = nums.length;
        int n = queries.length;
        int[] res = new int[n];
        Arrays.sort(nums);
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < n; i++){
            map.put(queries[i], i);
        }
        Arrays.sort(queries);
        int sum = 0;
        int idx = 0;
        for(int i = 0; i < m; i++){
            sum += nums[i];
            while(idx < n && sum > queries[idx]){
                res[map.get(queries[idx])] = i;
                idx++;
            }
            if(idx == n)
                break;
        }
        while(idx < n){
            res[map.get(queries[idx])] = m;
            idx++;
        }
        return res;
    }
}

前缀和加二分

from itertools import accumulate
from bisect import bisect_right

class Solution:
    def answerQueries(self, nums: List[int], queries: List[int]) -> List[int]:
        f = list(accumulate(sorted(nums)))
        return [bisect_right(f, q) for q in queries]

1626. 无矛盾的最佳球队

2023.03.22 每日一题

题目描述

假设你是球队的经理。对于即将到来的锦标赛,你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。

然而,球队中的矛盾会限制球员的发挥,所以必须选出一支 没有矛盾 的球队。如果一名年龄较小球员的分数 严格大于 一名年龄较大的球员,则存在矛盾。同龄球员之间不会发生矛盾。

给你两个列表 scores 和 ages,其中每组 scores[i] 和 ages[i] 表示第 i 名球员的分数和年龄。请你返回 所有可能的无矛盾球队中得分最高那支的分数 。

示例 1:

输入:scores = [1,3,5,10,15], ages = [1,2,3,4,5]
输出:34
解释:你可以选中所有球员。

示例 2:

输入:scores = [4,5,6,5], ages = [2,1,2,1]
输出:16
解释:最佳的选择是后 3 名球员。注意,你可以选中多个同龄球员。

示例 3:

输入:scores = [1,2,3,5], ages = [8,9,10,1]
输出:6
解释:最佳的选择是前 3 名球员。

提示:

1 <= scores.length, ages.length <= 1000
scores.length == ages.length
1 <= scores[i] <= 10^6
1 <= ages[i] <= 1000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/best-team-with-no-conflicts
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

排序以后,分数大的在后面,所以只需要判断年龄也大,那么就可以入队

class Solution {
    public int bestTeamScore(int[] scores, int[] ages) {
        //先按照分数和年龄排序
        //然后动态规划,对于当前位置,判断当前队员能加入的最大分数球队是哪一个

        int l = scores.length;
        int[][] people = new int[l][2];
        for(int i = 0; i < l; i++){
            people[i] = new int[]{scores[i], ages[i]};
        }
        //如果分数相同,那么按年龄从小到大排序
        Arrays.sort(people, (a, b) -> (a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]));
        int[] dp = new int[l];
        int res = 0;
        for(int i = 0; i < l; i++){
            for(int j = 0; j < i; j++){
                //如果当前年龄比前面的年龄大,那么可以加入,否则因为年龄小分高而被排挤
                if(people[i][1] >= people[j][1]){
                    dp[i] = Math.max(dp[i], dp[j]);
                }
            }
            //加上当前分数
            dp[i] += people[i][0];
            res = Math.max(res, dp[i]);
        }
        return res;
    }   
}
class Solution:
    def bestTeamScore(self, scores: List[int], ages: List[int]) -> int:
        people = sorted(zip(scores, ages))
        l = len(scores)
        dp = [0] * l
        res = 0
        for i in range(l):
            for j in range(i):
                if people[i][1] >= people[j][1]:
                    dp[i] = max(dp[i], dp[j])
            dp[i] += people[i][0]
            res = max(res, dp[i])
        return res
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值