链接:LeetCode
[Leetcode]2389. 和有限的最长子序列
给你一个长度为 n 的整数数组 nums ,和一个长度为 m 的整数数组 queries 。
返回一个长度为 m 的数组 answer ,其中 answer[i] 是 nums 中 元素之和小于等于 queries[i] 的 子序列 的 最大 长度 。
子序列 是由一个数组删除某些元素(也可以不删除)但不改变剩余元素顺序得到的一个数组。
前缀和+二分。
class Solution {
public int[] answerQueries(int[] nums, int[] queries) {
Arrays.sort(nums);
List<Integer> array = new ArrayList<>();
int result = 0;
for(var num:nums) {
result += num;
array.add(result);
}
int n = queries.length;
int[] res = new int[n];
for(int i=0;i<n;++i) {
res[i] = answer(array, queries[i]);
}
return res;
}
public int answer(List<Integer> nums, int target) {
// first larger index
int lo = 0, hi = nums.size() - 1;
while(lo <= hi) {
int mid = lo + ((hi-lo) >> 1);
if(nums.get(mid) <= target) lo = mid + 1;
else hi = mid - 1 ;
}
return lo;
}
}
[Leetcode]2390. 从字符串中移除星号
给你一个包含若干星号 * 的字符串 s 。
在一步操作中,你可以:
- 选中 s 中的一个星号。
- 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。
返回移除 所有 星号之后的字符串。
注意:
- 生成的输入保证总是可以执行题面中描述的操作。
- 可以证明结果字符串是唯一的。
栈模拟。
class Solution {
public String removeStars(String s) {
ArrayDeque<Character> queue = new ArrayDeque<Character>();
for(Character ch: s.toCharArray()) {
if(ch == '*') queue.removeLast();
else queue.addLast(ch);
}
StringBuilder sb = new StringBuilder();
for(var ch:queue) {
sb.append(ch);
}
return sb.toString();
}
}
[Leetcode]2391. 收集垃圾的最少总时间
给你一个下标从 0 开始的字符串数组 garbage ,其中 garbage[i] 表示第 i 个房子的垃圾集合。garbage[i] 只包含字符 'M' ,'P' 和 'G' ,但可能包含多个相同字符,每个字符分别表示一单位的金属、纸和玻璃。垃圾车收拾 一 单位的任何一种垃圾都需要花费 1 分钟。
同时给你一个下标从 0 开始的整数数组 travel ,其中 travel[i] 是垃圾车从房子 i 行驶到房子 i + 1 需要的分钟数。
城市里总共有三辆垃圾车,分别收拾三种垃圾。每辆垃圾车都从房子 0 出发,按顺序 到达每一栋房子。但它们 不是必须 到达所有的房子。
任何时刻只有 一辆 垃圾车处在使用状态。当一辆垃圾车在行驶或者收拾垃圾的时候,另外两辆车 不能 做任何事情。
请你返回收拾完所有垃圾需要花费的 最少 总分钟数。
贪心, 我们可以把每种垃圾分别处理,累加耗时。
注意到,答案其实可以分为两部分:
- 所有垃圾的数目,即 \(\textit{garbage}\) 中所有字符串的长度之和。
- 根据每一种字符在 \(\textit{garbage}\) 中最后一次出现的下标,即每辆垃圾车必须向右开到的房子的最小值,得到每辆车需要开的最短距离。
遍历 \(\textit{garbage}\) 可以求出。
class Solution {
public int garbageCollection(String[] garbage, int[] travel) {
int res = 0;
int idx1 = 0, idx2 = 0, idx3 = 0;
for(int i=0;i<garbage.length;++i) {
String gar = garbage[i];
res += gar.length();
if(gar.contains("M")) idx1 = i;
if(gar.contains("P")) idx2 = i;
if(gar.contains("G")) idx3 = i;
}
int n = travel.length, curSum = 0;
int[] prefixSum = new int[n+1];
for(int i=0;i<n;++i) {
curSum += travel[i];
prefixSum[i+1] = curSum;
}
res += prefixSum[idx1] + prefixSum[idx2] + prefixSum[idx3];
return res;
}
}
[Leetcode] 2392. 给定条件下构造矩阵
给你一个 正 整数 k ,同时给你:
- 一个大小为 n 的二维整数数组 rowConditions ,其中 rowConditions[i] = [abovei, belowi] 和
- 一个大小为 m 的二维整数数组 colConditions ,其中 colConditions[i] = [lefti, righti] 。
两个数组里的整数都是 1 到 k 之间的数字。
你需要构造一个 k x k 的矩阵,1 到 k 每个数字需要 恰好出现一次 。剩余的数字都是 0 。
矩阵还需要满足以下条件:
- 对于所有 0 到 n - 1 之间的下标 i ,数字 abovei 所在的 行 必须在数字 belowi 所在行的上面。
- 对于所有 0 到 m - 1 之间的下标 i ,数字 lefti 所在的 列 必须在数字 righti 所在列的左边。
返回满足上述要求的 任意 矩阵。如果不存在答案,返回一个空的矩阵。
拓扑排序。
数字之间的约束只发生在行与行、列于列,而行与列之间没有任何约束。因此我们可以分别处理行与列中数字的相对顺序
class Solution {
public int[][] buildMatrix(int k, int[][] rowConditions, int[][] colConditions) {
int[] rowOrder = getOrder(rowConditions, k), colOrder = getOrder(colConditions, k);
int[][] res = new int[k][k];
if(rowOrder[k-1] == 0 || colOrder[k-1] == 0) return new int[][]{};
HashMap<Integer, Integer> val2RowIdx = getIdx(rowOrder), val2ColIdx = getIdx(colOrder);
for(int i=1;i<k+1;++i) {
res[val2RowIdx.getOrDefault(i, 0)][val2ColIdx.getOrDefault(i, 0)] = i;
}
return res;
}
public int[] getOrder(int[][] conditions, int k) {
int[] indegree = new int[k];
// Note: 这里如果用HashSet去重,要注意判断conditions是否存在重复情况
HashMap<Integer, ArrayList<Integer>> hash = new HashMap<>();
for(var cond:conditions) {
int above = cond[0], below = cond[1];
hash.computeIfAbsent(above-1, key -> new ArrayList<Integer>()).add(below-1);
indegree[below-1] += 1;
}
int[] res = new int[k];
for(int i=0;i<k;++i) {
boolean zeroFalg = false;
int j = 0;
while(j<k) {
if(indegree[j] == 0) {
zeroFalg = true;
break;
}
++j;
}
if(!zeroFalg) break;
indegree[j] -= 1;
res[i] = j+1;
for(var nxt:hash.getOrDefault(j, new ArrayList<Integer>())) indegree[nxt] -= 1;
}
return res;
}
public HashMap<Integer, Integer> getIdx(int[] nums) {
HashMap<Integer, Integer> hash = new HashMap<>();
for(int i=0;i<nums.length;++i) {
hash.put(nums[i], i);
}
return hash;
}
}
参考:
LeetCode