范围内非常大的二进制数的异或 [L, R]
给定两个二进制字符串L和R ,任务是找到从 L 到 R 的异或。二进制字符串的长度是< = 10e6 。
例子:
Input: L = 10, R = 100
Output: 101
Explanation: L = 2 and R = 4 in decimal system.Therefore, the xor will be 2^3^4 = 5(101).
Input: L = 10, R = 10000
Output: 10001
朴素方法:解决问题的最简单方法是找到范围[L, R]中的所有二进制字符串,然后对所有二进制字符串执行 XOR 操作。
时间复杂度: (R – L +1) *(N) 其中 N 是二进制字符串R 的长度。
辅助空间: O(1)
有效的方法:上述方法可以通过观察进一步优化 -
- (L ^ (L+1) ^……^(R – 1) ^ R)可以写成(1^2^3 ^…. ^(R-1)^R) ^ (1^2^3 … .. ^(L-2) ^ (L-1))其中“^”表示元素的按位异或。所以问题被简化为找到从 1 到 n 的异或。
- 要计算从 1 到 n 的异或,通过用4对n取模来找到 n 的余数,并将其存储在一个变量中,比如rem , rem有四个可能的值——
- 如果rem =0则xor = n 。
- 如果rem = 1那么xor = 1 。
- 如果rem = 2那么xor = n+1 。
- 如果rem = 3那么xor = 0 。
观察以上几点后,按照以下步骤解决问题:
- 通过执行下面提到的步骤,创建一个从大小为 N 的二进制字符串S 中减去 1 的函数sub :
- 使用变量i在[N-1, 0]范围内迭代并执行以下步骤:
- 如果S[i] = '0' ,则将S[i]的值修改为1。
- 如果S[i] = '1' ,则将S[i]的值修改为0并终止循环。
- 返回字符串S作为答案。
- 使用变量i在[N-1, 0]范围内迭代并执行以下步骤:
- 通过执行下面提到的步骤,创建一个函数ad ,将 1 加到大小为 N 的二进制字符串S 上:
- 初始化一个变量,比如进位为0 。
- 使用变量i在[N-1, 0]范围内迭代并执行以下步骤:
- 如果S[i] = '1' ,则将S[i]的值修改为0并将进位的值修改为1 。
- 如果S[i] = '0' ,则将S[i]的值修改为1并将进位的值修改为0并终止循环。
- 如果进位 =1 ,则将S的值修改为'1' + S并返回字符串S 。
- 创建一个函数Xor_Finder ,通过执行以下步骤将 XOR 的值从1返回到S :
- 初始化一个变量,比如val并将值更新为S[n] + S[n-1]*2其中 n 是字符串S 的长度。
- 现在如果val = 0 ,则返回字符串S作为答案。
- 如果val = 1 ,则返回 '1' 作为答案。
- 如果val = 2 ,则返回ad(S)作为答案。
- 如果val = 3 ,则返回 0 作为答案。
- 创建一个函数final_xor ,通过执行下面提到的步骤计算两个二进制字符串L 和 R 的异或:
- 在L.size() != R.size()时将字符'0' 附加到字符串L中。
- 初始化一个字符串,比如说ans ,它将存储二进制字符串L和R的 xor 值。
- 使用变量i在[0, R.size()-1]范围内迭代并执行以下步骤:
- 如果L[i] = R[i] ,则在字符串ans 的末尾附加字符'0'。
- 如果L[i] != R[i] ,则将字符'1' 附加到字符串ans 的末尾。
- 返回字符串ans作为两个字符串的异或。
- 通过执行以下步骤,创建一个函数xorr以计算从L到R的 xor:
- 将L的值修改为sub(L) 。
- 通过调用函数xor_finder(L)和xor_finder(R)来修改L和R的值,分别计算从1到L和从1到R的 xor。
- 初始化一个变量,比如ans并通过将值更新为final_xor(L, R)来更新ans的值。
- 返回字符串ans作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to subtract one
// from the binary string
string sub(string s)
{
int n = s.size();
for (int i = n - 1; i >= 0; i--) {
// If the current character
// is 0 change it to 1
if (s[i] == '0') {
s[i] = '1';
}
else {
// If the character is 1
// Change is to 0 and
// terminate the loop
s[i] = '0';
break;
}
}
// Return the answer
return s;
}
// Function to add 1 in the
// binary string
string ad(string s)
{
int n = s.size();
int carry = 0;
for (int i = n - 1; i >= 0; i--) {
// If s[i]=='1' it
// will change s[i] to 0
// and carry = 1
if (s[i] == '1') {
carry = 1;
s[i] = '0';
}
else {
// If s[i]=='0' it
// will change s[i] to 1
// and carry = 0 and
// end the loop
carry = 0;
s[i] = '1';
break;
}
}
// If still carry left
// append character 1 to the
// beginning of the string
if (carry) {
s = '1' + s;
}
return s;
}
// Function to find xor from 1 to n
string xor_finder(string s)
{
int n = s.size() - 1;
// Variable val stores the
// remainder when binary string
// is divided by 4
int val = s[n] - '0';
val = val + (s[n - 1] - '0') * 2;
// If val == 0 the xor from
// 1 to n will be n itself
if (val == 0) {
return s;
}
else if (val == 1) {
// If val == the xor from
// 1 to n will be 1 itself
s = '1';
return s;
}
else if (val == 2) {
// If val == 2 the xor from
// 1 to n will be n+1 itself
return (ad(s));
}
else if (val == 3) {
// If val == 3 the xor from
// 1 to n will be 0 itself
s = '0';
return s;
}
}
// Function to find the xor of two
// binary string
string final_xor(string L, string R)
{
// Using loop to equalise the size
// of string L and R
while (L.size() != R.size()) {
L = '0' + L;
}
string ans = "";
for (int i = 0; i < L.size(); i++) {
// If ith bit of L is 0 and
// ith bit of R is 0
// then xor will be 0
if (L[i] == '0' && R[i] == '0') {
ans += '0';
}
else if (L[i] == '0' && R[i] == '1'
|| L[i] == '1' && R[i] == '0') {
// If ith bit of L is 0 and
// ith bit of R is 1 or
// vice versa then xor will be 1
ans += '1';
}
else {
// If ith bit of L is 1 and
// ith bit of R is 1
// then xor will be 0
ans += '0';
}
}
return ans;
}
// Function to find xor from L to R
string xorr(string L, string R)
{
// changing L to L - 1
L = sub(L);
// Finding xor from 1 to L - 1
L = xor_finder(L);
// Finding xor from 1 to R
R = xor_finder(R);
// Xor of 1, 2, ..., L-1 and 1, 2, ...., R
string ans = final_xor(L, R);
return ans;
}
// Driver Code
int main()
{
// Given Input
string L = "10", R = "10000";
// Function Call
cout << xorr(L, R) << endl;
return 0;
}
Java
// Java program for above approach
class GFG{
// Function to subtract one
// from the binary string
public static String sub(String s)
{
StringBuilder new_s = new StringBuilder(s);
int n = s.length();
for(int i = n - 1; i >= 0; i--)
{
// If the current character
// is 0 change it to 1
if (s.charAt(i) == '0')
{
new_s.setCharAt(i, '1');
}
else
{
// If the character is 1
// Change is to 0 and
// terminate the loop
new_s.setCharAt(i, '0');
break;
}
}
// Return the answer
return new_s.toString();
}
// Function to add 1 in the
// binary string
public static String ad(String s)
{
int n = s.length();
StringBuilder new_s = new StringBuilder(s);
int carry = 0;
for(int i = n - 1; i >= 0; i--)
{
// If s[i]=='1' it
// will change s[i] to 0
// and carry = 1
if (s.charAt(i) == '1')
{
carry = 1;
new_s.setCharAt(i, '0');
}
else
{
// If s[i]=='0' it
// will change s[i] to 1
// and carry = 0 and
// end the loop
carry = 0;
new_s.setCharAt(i, '1');
break;
}
}
// If still carry left
// append character 1 to the
// beginning of the string
if (carry != 0)
{
s = '1' + new_s.toString();
}
return s;
}
// Function to find xor from 1 to n
public static String xor_finder(String s)
{
int n = s.length() - 1;
// Variable val stores the
// remainder when binary string
// is divided by 4
int val = s.charAt(n) - '0';
val = val + (s.charAt(n - 1) - '0') * 2;
// If val == 0 the xor from
// 1 to n will be n itself
if (val == 0)
{
return s;
}
else if (val == 1)
{
// If val == 1 the xor from
// 1 to n will be 1 itself
s = "1";
return s;
}
else if (val == 2)
{
// If val == 2 the xor from
// 1 to n will be n+1 itself
return (ad(s));
}
else
{
// If val == 3 the xor from
// 1 to n will be 0 itself
s = "0";
return s;
}
}
// Function to find the xor of two
// binary string
public static String final_xor(String L, String R)
{
// Using loop to equalise the size
// of string L and R
while (L.length() != R.length())
{
L = '0' + L;
}
String ans = "";
for(int i = 0; i < L.length(); i++)
{
// If ith bit of L is 0 and
// ith bit of R is 0
// then xor will be 0
if (L.charAt(i) == '0' && R.charAt(i) == '0')
{
ans += '0';
}
else if (L.charAt(i) == '0' && R.charAt(i) == '1' ||
L.charAt(i) == '1' && R.charAt(i) == '0')
{
// If ith bit of L is 0 and
// ith bit of R is 1 or
// vice versa then xor will be 1
ans += '1';
}
else
{
// If ith bit of L is 1 and
// ith bit of R is 1
// then xor will be 0
ans += '0';
}
}
return ans;
}
// Function to find xor from L to R
public static String xorr(String L, String R)
{
// Changing L to L - 1
L = sub(L);
// Finding xor from 1 to L - 1
L = xor_finder(L);
// Finding xor from 1 to R
R = xor_finder(R);
// Xor of 1, 2, ..., L-1 and 1, 2, ...., R
String ans = final_xor(L, R);
return ans;
}
// Driver code
public static void main(String[] args)
{
// Given Input
String L = "10", R = "10000";
// Function Call
System.out.println(xorr(L, R));
}
}
// This code is contributed by garry133
Python3
# Python program for the above approach
# Function to subtract one
# from the binary string
def sub(s):
# Changing string into list to change
# the characters in O(1)
s = list(s)
n = len(s)
for i in range(n-1, -1, -1):
# If the current character
# is 0 change it to 1
if (s[i] == '0'):
s[i] = '1'
else:
# If the character is 1
# Change is to 0 and
# terminate the loop
s[i] = '0'
break
# Return the answer
# converting list to string
s = "".join(s)
return s
# Function to add 1 in the
# binary string
def ad(s):
n = len(s)
carry = 0
for i in range(n-1, -1, -1):
# If s[i]=='1' it
# will change s[i] to 0
# and carry = 1
if (s[i] == '1'):
carry = 1
s[i] = '0'
else:
# If s[i]=='0' it
# will change s[i] to 1
# and carry = 0 and
# end the loop
carry = 0
s[i] = '1'
break
# If still carry left
# append character 1 to the
# beginning of the string
if (carry):
s = '1' + s
return s
# Function to find xor from 1 to n
def xor_finder(s):
n = len(s) - 1
# Variable val stores the
# remainder when binary string
# is divided by 4
val = ord(s[n]) - 48
val = val + (ord(s[n - 1]) - 48) * 2
# If val == 0 the xor from
# 1 to n will be n itself
if (val == 0):
return s
else if (val == 1):
# If val == the xor from
# 1 to n will be 1 itself
s = '1'
return s
else if (val == 2):
# If val == 2 the xor from
# 1 to n will be n+1 itself
return (ad(s))
else if (val == 3):
# If val == 3 the xor from
# 1 to n will be 0 itself
s = '0'
return s
# Function to find the xor of two
# binary string
def final_xor(L, R):
# Using loop to equalise the size
# of string L and R
while (len(L) != len(R)):
L = '0' + L
ans = ""
for i in range(len(L)):
# If ith bit of L is 0 and
# ith bit of R is 0
# then xor will be 0
if (L[i] == '0' and R[i] == '0'):
ans += '0'
else if (L[i] == '0' and R[i] == '1'
or L[i] == '1' and R[i] == '0'):
# If ith bit of L is 0 and
# ith bit of R is 1 or
# vice versa then xor will be 1
ans += '1'
else:
# If ith bit of L is 1 and
# ith bit of R is 1
# then xor will be 0
ans += '0'
return ans
# Function to find xor from L to R
def xorr(L, R):
# changing L to L - 1
L = sub(L)
# Finding xor from 1 to L - 1
L = xor_finder(L)
# Finding xor from 1 to R
R = xor_finder(R)
# Xor of 1, 2, ..., L-1 and 1, 2, ...., R
ans = final_xor(L, R)
return ans
# Driver Code
# Given Input
L = "10"
R = "10000"
# Function Call
print(xorr(L, R))
# This code is contributed by rj13to.
输出:
10001
时间复杂度: O(N) 其中 N 是字符串的长度
辅助空间: O(N)