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