子字符串异或查询
难度:
标签:
题目描述
You are given a binary string s
, and a 2D integer array queries
where queries[i] = [firsti, secondi]
.
For the ith
query, find the shortest substring of s
whose decimal value, val
, yields secondi
when bitwise XORed with firsti
. In other words, val ^ firsti == secondi
.
The answer to the ith
query is the endpoints (0-indexed) of the substring [lefti, righti]
or [-1, -1]
if no such substring exists. If there are multiple answers, choose the one with the minimum lefti
.
Return an array ans
where ans[i] = [lefti, righti]
is the answer to the ith
query.
A substring is a contiguous non-empty sequence of characters within a string.
Example 1:
Input: s = "101101", queries = [[0,5],[1,2]] Output: [[0,2],[2,3]] Explanation: For the first query the substring in range[0,2]
is "101" which has a decimal value of5
, and5 ^ 0 = 5
, hence the answer to the first query is[0,2]
. In the second query, the substring in range[2,3]
is "11", and has a decimal value of 3, and 3^ 1 = 2
. So,[2,3]
is returned for the second query.
Example 2:
Input: s = "0101", queries = [[12,8]]
Output: [[-1,-1]]
Explanation: In this example there is no substring that answers the query, hence [-1,-1] is returned
.
Example 3:
Input: s = "1", queries = [[4,5]] Output: [[0,0]] Explanation: For this example, the substring in range[0,0]
has a decimal value of1
, and1 ^ 4 = 5
. So, the answer is[0,0]
.
Constraints:
1 <= s.length <= 104
s[i]
is either'0'
or'1'
.1 <= queries.length <= 105
0 <= firsti, secondi <= 109
代码结果
运行时间: 107 ms, 内存: 57.3 MB
/*
* Approach using Java Streams:
* 1. Generate all possible substrings of the binary string s.
* 2. Use streams to filter and find the shortest substring matching the query conditions.
* 3. Return the indices of the substring or [-1, -1] if no such substring exists.
*/
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class Solution {
public int[][] solveQueries(String s, int[][] queries) {
int n = s.length();
int[][] result = new int[queries.length][2];
for (int i = 0; i < queries.length; i++) {
int first = queries[i][0];
int second = queries[i][1];
result[i][0] = -1;
result[i][1] = -1;
int minLength = Integer.MAX_VALUE;
for (int start = 0; start < n; start++) {
int finalI = i;
IntStream.range(start, n).forEach(end -> {
String subStr = s.substring(start, end + 1);
int val = Integer.parseInt(subStr, 2);
if ((val ^ first) == second && (end - start + 1) < minLength) {
result[finalI][0] = start;
result[finalI][1] = end;
minLength = end - start + 1;
}
});
}
}
return result;
}
public static void main(String[] args) {
Solution solution = new Solution();
String s = "101101";
int[][] queries = {{0, 5}, {1, 2}};
int[][] result = solution.solveQueries(s, queries);
for (int[] res : result) {
System.out.println("[" + res[0] + ", " + res[1] + "]");
}
}
}
解释
方法:
这个题解的思路基于预处理和哈希表的使用。首先,题解构建一个哈希表来存储所有可能的子字符串及其对应的起始和结束位置。算法首先检测字符串中的第一个'0'字符,并记录其位置(只记录第一个零是因为任何以0开始的子字符串的十进制值都是0)。然后,对于字符串中的每个'1'开始的位置,算法计算以该位置开始的所有可能长度(最长为30位,足以表示所有整数)的子字符串的十进制值,并将这些值及其对应的起始和结束位置存储在哈希表中。最后,对于每个查询,算法通过计算查询的异或值是否存在于哈希表中来直接返回答案,从而避免了多次计算。
时间复杂度:
O(n + q)
空间复杂度:
O(n + q)
代码细节讲解
🦆
为什么在处理二进制字符串时,只关注以'1'开始的子字符串而忽略以'0'开始的子字符串?
▷🦆
题解中提到的'记录第一个0的位置,因为0异或任何数都是那个数'这一点是否准确?0异或一个数确实得到该数,但这是否意味着我们只需记录第一个0的位置?
▷🦆
题解中提到计算子字符串十进制值的循环是最多30位长,这个长度30是如何确定的?是否有特定的理由选择30作为长度上限?
▷