[Leetcode Weekly Contest]332
链接:LeetCode
[Leetcode]2562. 找出数组的串联值
给你一个下标从 0 开始的整数数组 nums 。
现定义两个数字的 串联 是由这两个数值串联起来形成的新数字。
例如,15 和 49 的串联是 1549 。
nums 的 串联值 最初等于 0 。执行下述操作直到 nums 变为空:
如果 nums 中存在不止一个数字,分别选中 nums 中的第一个元素和最后一个元素,将二者串联得到的值加到 nums 的 串联值 上,然后从 nums 中删除第一个和最后一个元素。
如果仅存在一个元素,则将该元素的值加到 nums 的串联值上,然后删除这个元素。
返回执行完所有操作后 nums 的串联值。
遍历即可。
class Solution {
public long findTheArrayConcVal(int[] nums) {
int first=0, last = nums.length-1;
long res = 0L;
while(first <= last) {
if(first == last) res += nums[first];
else {
res += concat(nums[first] , nums[last]);
}
first ++;
last --;
}
return res;
}
public int concat(int num1, int num2) {
int length = 1, temp = num2;
while(temp!=0) {
length *= 10;
temp /= 10;
}
return num1 * length + num2;
}
}
[Leetcode]2563. 统计公平数对的数目
给你一个下标从 0 开始、长度为 n 的整数数组 nums ,和两个整数 lower 和 upper ,返回 公平数对的数目 。
如果 (i, j) 数对满足以下情况,则认为它是一个 公平数对 :
- 0 <= i < j < n,且
- lower <= nums[i] + nums[j] <= upper
由于排序不会影响数对的个数,为了能够二分,可以先排序。
然后枚举 nums[i],二分查找符合要求的nums[j] 的个数。
class Solution {
public long countFairPairs(int[] nums, int lower, int upper) {
Arrays.sort(nums);
long res = 0L;
for(int i=0;i<nums.length;++i) {
int left = getFirstLargerOrEqualIndex(nums, lower-nums[i]);
int right = getLastSmallerOrEqualIndex(nums, upper-nums[i]);
if(i>=left && i<=right)res += right-left;
else res += right-left+1;
}
return res/2;
}
public int getFirstLargerOrEqualIndex(int[] nums, int target) {
int lo=0, hi = nums.length-1;
while(lo<=hi) {
int mid = lo+((hi-lo)>>1);
if(target <= nums[mid]) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return lo;
}
public int getLastSmallerOrEqualIndex(int[] nums, int target) {
int lo=0, hi = nums.length-1;
while(lo<=hi) {
int mid = lo+((hi-lo)>>1);
if(target < nums[mid]) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return hi;
}
}
[Leetcode]2564. 子字符串异或查询
给你一个 二进制字符串 s 和一个整数数组 queries ,其中 queries[i] = [firsti, secondi] 。
对于第 i 个查询,找到 s 的 最短子字符串 ,它对应的 十进制值 val 与 firsti 按位异或 得到 secondi ,换言之,val ^ firsti == secondi 。
第 i 个查询的答案是子字符串 [lefti, righti] 的两个端点(下标从 0 开始),如果不存在这样的子字符串,则答案为 [-1, -1] 。如果有多个答案,请你选择 lefti 最小的一个。
请你返回一个数组 ans ,其中 ans[i] = [lefti, righti] 是第 i 个查询的答案。
子字符串 是一个字符串中一段连续非空的字符序列。
问题等价于在 s 中找到值为 second⊕first 的数。
由于 \(10^9 < 2^30\), 我们可以直接预计算所有 s 中长度不超过 30 的数及其对应的 left 和 right,记到一个哈希表中,然后 O(1) 地回答询问。
class Solution {
private static final int[] NOT_FOUND = new int[]{-1, -1};
public int[][] substringXorQueries(String S, int[][] queries) {
var m = new HashMap<Integer, int[]>();
int i = S.indexOf('0');
if (i >= 0) m.put(0, new int[]{i, i}); // 这样下面就可以直接跳过 '0' 了,效率更高
var s = S.toCharArray();
for (int l = 0, n = s.length; l < n; ++l) {
if (s[l] == '0') continue;
for (int r = l, x = 0; r < Math.min(l + 30, n); ++r) {
x = x << 1 | (s[r] & 1);
m.putIfAbsent(x, new int[]{l, r});
}
}
var ans = new int[queries.length][];
for (i = 0; i < queries.length; i++)
ans[i] = m.getOrDefault(queries[i][0] ^ queries[i][1], NOT_FOUND);
return ans;
}
}
[Leetcode]2565. 最少得分子序列
给你两个字符串 s 和 t 。
你可以从字符串 t 中删除任意数目的字符。
如果没有从字符串 t 中删除字符,那么得分为 0 ,否则:
- 令 left 为删除字符中的最小下标。
- 令 right 为删除字符中的最大下标。
字符串的得分为 right - left + 1 。
请你返回使 t 成为 s 子序列的最小得分。
一个字符串的 子序列 是从原字符串中删除一些字符后(也可以一个也不删除),剩余字符不改变顺序得到的字符串。(比方说 "ace" 是 "abcde" 的子序列,但是 "aec" 不是)
前后缀分解+双指针.
left和right之间的都删掉,不违背题目的意愿,也更好地成为子序列。我们直接计算 s 的前缀 s[:i] 能够匹配 t 的前缀的最大长度 prefix[i],计算 s 的后缀 s[i:] 能够匹配 t 的前缀的最大长度 suffix[i],枚举 s 的前缀与后缀,找到前缀 s[:i] 与 后缀 s[(i+1):] 的最长匹配的之和,找到最大的前缀和匹配之和即可。
prefix[i]+suffix[i+1] 一定满足小于 n 的,否则两个字符串完全匹配直接返回 0。
class Solution {
public int minimumScore(String s, String t) {
int sn = s.length();
int tn = t.length();
int [] prefix_cnt = new int[sn + 1];
int [] suffix_cnt = new int[sn + 1];
prefix_cnt[0] = 0;
int ti = 0;
int cnt = 0;
for (int si = 0; si < sn; si ++){
if (ti < tn && s.charAt(si) == t.charAt(ti)){
ti ++;
cnt ++;
}
prefix_cnt[si + 1] = cnt;
}
suffix_cnt[sn] = 0;
ti = tn - 1;
cnt = 0;
for (int si = sn - 1; si > -1; si --){
if (0 <= ti && s.charAt(si) == t.charAt(ti)){
ti --;
cnt ++;
}
suffix_cnt[si] = cnt;
}
int res = tn;
for (int si = 0; si < sn + 1; si ++){
int cur = tn - (prefix_cnt[si] + suffix_cnt[si]);
cur = Math.max(0, cur);
res = Math.min(res, cur);
}
return res;
}
}
参考:LeetCode