[Leetcode Weekly Contest]367
链接:LeetCode
[Leetcode]2903. 找出满足差值条件的下标 I
给你一个下标从 0 开始、长度为 n 的整数数组 nums ,以及整数 indexDifference 和整数 valueDifference 。
你的任务是从范围 [0, n - 1] 内找出 2 个满足下述所有条件的下标 i 和 j :
- abs(i - j) >= indexDifference 且
- abs(nums[i] - nums[j]) >= valueDifference
返回整数数组 answer。如果存在满足题目要求的两个下标,则 answer = [i, j] ;否则,answer = [-1, -1] 。如果存在多组可供选择的下标对,只需要返回其中任意一组即可。
注意:i 和 j 可能 相等 。
遍历循环即可。
class Solution {
public int[] findIndices(int[] nums, int indexDifference, int valueDifference) {
int[] res = new int[] {-1,-1};
int n = nums.length;
for(int i=0;i<n;++i) {
for(int j=i+indexDifference;j<n;++j) {
if(Math.abs(nums[j]-nums[i]) >= valueDifference) {
res[0] = i;
res[1] = j;
return res;
}
}
}
return res;
}
}
[Leetcode]2904. 最短且字典序最小的美丽子字符串
如果 s 的某个子字符串中 1 的个数恰好等于 k ,则称这个子字符串是一个 美丽子字符串 。
令 len 等于 最短 美丽子字符串的长度。
返回长度等于 len 且字典序 最小 的美丽子字符串。如果 s 中不含美丽子字符串,则返回一个 空 字符串。
对于相同长度的两个字符串 a 和 b ,如果在 a 和 b 出现不同的第一个位置上,a 中该位置上的字符严格大于 b 中的对应字符,则认为字符串 a 字典序 大于 字符串 b 。
例如,"abcd" 的字典序大于 "abcc" ,因为两个字符串出现不同的第一个位置对应第四个字符,而 d 大于 c 。
滑动窗口。如果窗口内的 1 的个数超过 k,或者窗口端点是 0,就可以缩小窗口。
class Solution {
public String shortestBeautifulSubstring(String s, int k) {
String res = "";
int minLength = Integer.MAX_VALUE;
int start = 0, count = 0;
for(int i=0;i<s.length();++i) {
if(s.charAt(i) == '1') count ++;
while (start < i && (count > k || s.charAt(start) == '0')) {
count -= (s.charAt(start) - '0');
start ++;
}
if(count == k) {
if(i-start+1 <= minLength) {
if(i-start+1 == minLength) res = getMinString(res, s.substring(start, i+1));
else res = s.substring(start, i+1);
minLength = i-start+1;
}
}
}
return res;
}
private String getMinString(String a, String b) {
for(int i=0;i<a.length();++i) {
if(a.charAt(i) < b.charAt(i)) return a;
else if(a.charAt(i) > b.charAt(i)) return b;
}
return a;
}
}
[Leetcode]2905. 找出满足差值条件的下标 II
给你一个下标从 0 开始、长度为 n 的整数数组 nums ,以及整数 indexDifference 和整数 valueDifference 。
你的任务是从范围 [0, n - 1] 内找出 2 个满足下述所有条件的下标 i 和 j :
- abs(i - j) >= indexDifference 且
- abs(nums[i] - nums[j]) >= valueDifference
返回整数数组 answer。如果存在满足题目要求的两个下标,则 answer = [i, j] ;否则,answer = [-1, -1] 。如果存在多组可供选择的下标对,只需要返回其中任意一组即可。
注意:i 和 j 可能 相等 。
滑动窗口。维护每个元素的前缀和后缀的最大值和最小值的「下标」;模拟窗口大小为 indexDifference 的滑动窗口,判断端点的前后缀的最值能否构造目标方案。另外,可以我们发现最值具备单调性,因此我们没必要预处理所有下标的最值,可以在一次遍历的过程中边维护最值,边检查方案。
class Solution {
public int[] findIndices(int[] nums, int indexDifference, int valueDifference) {
int[] res = new int[]{-1, -1};
int min = nums[0], max = nums[0];
// Also can use two points to point to the min index and max index
Map<Integer, Integer> indexs = new HashMap<>();
for(int i=indexDifference;i<nums.length;++i) {
min = Math.min(min, nums[i-indexDifference]);
max = Math.max(max, nums[i-indexDifference]);
indexs.put(nums[i-indexDifference],i-indexDifference);
if(nums[i] - min >= valueDifference) {
res[0] = i;
res[1] = indexs.get(min);
return res;
}
if(max - nums[i] >= valueDifference) {
res[0] = i;
res[1] = indexs.get(max);
return res;
}
}
return res;
}
}
[Leetcode]2906. 构造乘积矩阵
给你一个下标从 0 开始、大小为 n * m 的二维整数矩阵 grid ,定义一个下标从 0 开始、大小为 n * m 的的二维矩阵 p。如果满足以下条件,则称 p 为 grid 的 乘积矩阵 :
对于每个元素 p[i][j] ,它的值等于除了 grid[i][j] 外所有元素的乘积。乘积对 12345 取余数。
返回 grid 的乘积矩阵。
前后缀分解。核心思想:把矩阵拉成一维的,我们需要算出每个数左边所有数的乘积,以及右边所有数的乘积,这都可以用递推得到。
时间复杂度:\(\mathcal{O}(nm)\),其中 n 和 m 分别为 \(\textit{grid}\) 的行数和列数。
空间复杂度:\(\mathcal{O}(1)\)。返回值不计入。
class Solution {
public int[][] constructProductMatrix(int[][] grid) {
int n = grid.length, m = grid[0].length;
int[][] res = new int[n][m];
int[] left = new int[n*m];
int[] right = new int[n*m];
Arrays.fill(left, 1);
Arrays.fill(right, 1);
for(int i=0;i<n;++i) {
for(int j=0;j<m;++j) {
if(i == n-1 && j == m-1) continue;
left[i*m+j+1] = (left[i*m+j] * (grid[i][j] % 12345))% 12345;
}
}
for(int i=n-1;i>=0;--i) {
for(int j=m-1;j>=0;--j) {
if(i == 0 && j == 0) continue;
right[i*m+j-1] = (right[i*m+j] * (grid[i][j] % 12345))% 12345;
}
}
for(int i=0;i<n;++i) {
for(int j=0;j<m;++j) {
res[i][j] = (left[i*m+j] * right[i*m+j]) % 12345;
}
}
return res;
}
}
参考:LeetCode