LeetCode第226场周赛
题目:1742. 盒子中小球的最大数量
你在一家生产小球的玩具厂工作,有 n 个小球,编号从 lowLimit 开始,到 highLimit 结束(包括 lowLimit 和 highLimit ,即 n == highLimit - lowLimit + 1)。另有无限数量的盒子,编号从 1 到 infinity 。
你的工作是将每个小球放入盒子中,其中盒子的编号应当等于小球编号上每位数字的和。例如,编号 321 的小球应当放入编号 3 + 2 + 1 = 6 的盒子,而编号 10 的小球应当放入编号 1 + 0 = 1 的盒子。
给你两个整数 lowLimit 和 highLimit ,返回放有最多小球的盒子中的小球数量。如果有多个盒子都满足放有最多小球,只需返回其中任一盒子的小球数量。
示例 1:
输入:lowLimit = 1, highLimit = 10
输出:2
解释:
盒子编号:1 2 3 4 5 6 7 8 9 10 11 …
小球数量:2 1 1 1 1 1 1 1 1 0 0 …
编号 1 的盒子放有最多小球,小球数量为 2 。
示例 2:
输入:lowLimit = 5, highLimit = 15
输出:2
解释:
盒子编号:1 2 3 4 5 6 7 8 9 10 11 …
小球数量:1 1 1 1 2 2 1 1 1 0 0 …
编号 5 和 6 的盒子放有最多小球,每个盒子中的小球数量都是 2 。
示例 3:
输入:lowLimit = 19, highLimit = 28
输出:2
解释:
盒子编号:1 2 3 4 5 6 7 8 9 10 11 12 …
小球数量:0 1 1 1 1 1 1 1 1 2 0 0 …
编号 10 的盒子放有最多小球,小球数量为 2 。
提示:
1 <= lowLimit <= highLimit <= 105
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-number-of-balls-in-a-box
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:
依照题目意思算出每个球的编号放入桶中,统计一下每个桶中球的数量求个最大值。
class Solution {
public int countBalls(int l, int r) {
int[] h = new int[50]; // r 最大值不超过10^5次方,所以各位数的和不会超过50
int ans = 0;
for(int i = l; i <= r; i++) {
int c = i, sum = 0;
while(c > 0) {
sum += c %10;
c /= 10;
}
h[sum]++;
ans = Math.max(ans, h[sum]);
}
return ans;
}
}
题目:1743. 从相邻元素对还原数组
存在一个由 n 个不同元素组成的整数数组 nums ,但你已经记不清具体内容。好在你还记得 nums 中的每一对相邻元素。
给你一个二维整数数组 adjacentPairs ,大小为 n - 1 ,其中每个 adjacentPairs[i] = [ui, vi] 表示元素 ui 和 vi 在 nums 中相邻。
题目数据保证所有由元素 nums[i] 和 nums[i+1] 组成的相邻元素对都存在于 adjacentPairs 中,存在形式可能是 [nums[i], nums[i+1]] ,也可能是 [nums[i+1], nums[i]] 。这些相邻元素对可以 按任意顺序 出现。
返回 原始数组 nums 。如果存在多种解答,返回 其中任意一个 即可。
示例 1:
输入:adjacentPairs = [[2,1],[3,4],[3,2]]
输出:[1,2,3,4]
解释:数组的所有相邻元素对都在 adjacentPairs 中。
特别要注意的是,adjacentPairs[i] 只表示两个元素相邻,并不保证其 左-右 顺序。
示例 2:
输入:adjacentPairs = [[4,-2],[1,4],[-3,1]]
输出:[-2,4,1,-3]
解释:数组中可能存在负数。
另一种解答是 [-3,1,4,-2] ,也会被视作正确答案。
示例 3:
输入:adjacentPairs = [[100000,-100000]]
输出:[100000,-100000]
提示:
nums.length == n
adjacentPairs.length == n - 1
adjacentPairs[i].length == 2
2 <= n <= 105
-105 <= nums[i], ui, vi <= 105
题目数据保证存在一些以 adjacentPairs 作为元素对的数组 nums
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/restore-the-array-from-adjacent-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:邻接表
将所有相邻节点存入邻接表中,然后找出头节点(出现次数为一的点),然后依次按顺序找。
class Solution {
public HashMap<Integer, List<Integer>> edge;
public int[] restoreArray(int[][] a) {
int n = a.length;
HashMap<Integer, Integer> cnt = new HashMap<>();
edge = new HashMap<>();
for (int i = 0; i < n; i++) {
cnt.put(a[i][0], cnt.getOrDefault(a[i][0], 0) + 1);
cnt.put(a[i][1], cnt.getOrDefault(a[i][1], 0) + 1);
List<Integer> a1 = edge.getOrDefault(a[i][0], new ArrayList<>());
List<Integer> a2 = edge.getOrDefault(a[i][1], new ArrayList<>());
a1.add(a[i][1]);
a2.add(a[i][0]);
edge.put(a[i][0], a1);
edge.put(a[i][1], a2);
}
int root = 0;
for (Map.Entry<Integer, Integer> entry : cnt.entrySet()) {
if (entry.getValue() == 1) {
root = entry.getKey();
break;
}
}
int[] ans = new int[n + 1];
dfs(root, 1000000, ans, 0);
return ans;
}
private void dfs(int root, int f, int[] p, int idx) {
p[idx] = root;
for (int x : edge.get(root)) {
if (x != f) {
dfs(x, root, p, idx + 1);
}
}
}
}
题目:1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
给你一个下标从 0 开始的正整数数组 candiesCount ,其中 candiesCount[i] 表示你拥有的第 i 类糖果的数目。同时给你一个二维数组 queries ,其中 queries[i] = [favoriteTypei, favoriteDayi, dailyCapi] 。
你按照如下规则进行一场游戏:
你从第 0 天开始吃糖果。
你在吃完 所有 第 i - 1 类糖果之前,不能 吃任何一颗第 i 类糖果。
在吃完所有糖果之前,你必须每天 至少 吃 一颗 糖果。
请你构建一个布尔型数组 answer ,满足 answer.length == queries.length 。answer[i] 为 true 的条件是:在每天吃 不超过 dailyCapi 颗糖果的前提下,你可以在第 favoriteDayi 天吃到第 favoriteTypei 类糖果;否则 answer[i] 为 false 。注意,只要满足上面 3 条规则中的第二条规则,你就可以在同一天吃不同类型的糖果。
请你返回得到的数组 answer 。
示例 1:
输入:candiesCount = [7,4,5,3,8], queries = [[0,2,2],[4,2,4],[2,13,1000000000]]
输出:[true,false,true]
提示:
1- 在第 0 天吃 2 颗糖果(类型 0),第 1 天吃 2 颗糖果(类型 0),第 2 天你可以吃到类型 0 的糖果。
2- 每天你最多吃 4 颗糖果。即使第 0 天吃 4 颗糖果(类型 0),第 1 天吃 4 颗糖果(类型 0 和类型 1),你也没办法在第 2 天吃到类型 4 的糖果。换言之,你没法在每天吃 4 颗糖果的限制下在第 2 天吃到第 4 类糖果。
3- 如果你每天吃 1 颗糖果,你可以在第 13 天吃到类型 2 的糖果。
示例 2:
输入:candiesCount = [5,2,6,4,1], queries = [[3,1,2],[4,10,3],[3,10,100],[4,100,30],[1,3,1]]
输出:[false,true,true,false,false]
提示:
1 <= candiesCount.length <= 105
1 <= candiesCount[i] <= 105
1 <= queries.length <= 105
queries[i].length == 3
0 <= favoriteTypei < candiesCount.length
0 <= favoriteDayi <= 109
1 <= dailyCapi <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/can-you-eat-your-favorite-candy-on-your-favorite-day
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:前缀和
题目大致意思是给你一些询问q,请问在q[i]次询问,是否q[i, favoriteDayi]天吃到q[i, favoriteTypei]类糖果,且每天吃的糖果不超过q[i, dailyCapi]颗且每天至少吃1颗,且在吃完第 i - 1类糖果前不能吃第 i 类糖果,如果都满足则这次询问则为true,否则为false。
我们只要判断在第q[i, favoriteDayi] + 1天是否能吧q[i, favoriteTypei] - 1 类糖果吃完,且q[i, favoriteDayi] + 1天我还能吃至少1颗糖果,且在保证每天吃一颗糖果的情况下,q[i, favoriteDayi]天不能超过 0 至 q[i, favoriteTypei]类糖果的总和。
所以我们预处理一个前缀和,我们就能在很快时间内知道是否能在第q[i, favoriteDayi] + 1天是否能吧q[i, favoriteTypei] - 1 类糖果吃完,且q[i, favoriteDayi]天吃的糖果不超过 0 至 q[i, favoriteTypei]类糖果的总和。
class Solution {
public boolean[] canEat(int[] candiesCount, int[][] queries) {
int n = queries.length, m = candiesCount.length;
boolean[] ans = new boolean[n];
long[] sum = new long[m + 1];
for(int i = 1; i <= m; i++) sum[i] = sum[i - 1] + candiesCount[i - 1];
for(int i = 0; i < n; i++) {
long s = sum[queries[i][0]];
ans[i] = s < (long)(queries[i][1] + 1) * queries[i][2] && queries[i][1] < sum[queries[i][0] + 1];
}
return ans;
}
}
题目:1745. 回文串分割 IV
给你一个字符串 s ,如果可以将它分割成三个 非空 回文子字符串,那么返回 true ,否则返回 false 。
当一个字符串正着读和反着读是一模一样的,就称其为 回文字符串 。
示例 1:
输入:s = “abcbdd”
输出:true
解释:“abcbdd” = “a” + “bcb” + “dd”,三个子字符串都是回文的。
示例 2:
输入:s = “bcbddxy”
输出:false
解释:s 没办法被分割成 3 个回文子字符串。
提示:
3 <= s.length <= 2000
s 只包含小写英文字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:dp
题目说将字符串分成三个非空部分,也就是在字符串中选两个点,将字符分成三个非空子串,我们可以枚举所有点,判断一下是否是回文。
判断是否是回文,先预处理一个数组,a[i, j] 表示在字符串中 i - j 是否是回文。这样我们就可以在o(1)的时间内判断一个区间是否是回文。
class Solution {
public boolean checkPartitioning(String s) {
int n = s.length();
boolean[][] f = new boolean[n][n];
for(int i = n - 1; i >= 0; i --) {
for(int j = n - 1; j >= i; j--) {
if(i == j) f[i][j] = true;
else {
f[i][j] = s.charAt(i) == s.charAt(j);
if(i < n - 1 && i + 1 != j) f[i][j] = f[i][j] && f[i + 1][j - 1];
}
}
}
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++)
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) return true;
}
return false;
}
}