Problem of The Day: Minimize XOR
Problem Statement

Intuition
The problem is to construct a number that has the same number of set bits (1s) as num2, while minimizing the XOR result with num1.
The key observation is that XOR minimizes when the constructed number (res) has its bits as close as possible to num1. To achieve this, prioritize setting the most significant bits of num1 in res while respecting the number of set bits required.
Approach
-
Count the set bits in
num2:- Use bitwise operations to calculate the number of 1s in
num2(set_bit).
- Use bitwise operations to calculate the number of 1s in
-
Identify the leftmost bit position in
num1:- Iterate through the bits of
num1to find its most significant bit.
- Iterate through the bits of
-
Construct the result:
- Start with
res = 0and try to set bits inresfrom most significant to least significant:- Use the bits of
num1when they are set. - Stop setting bits from
num1when the required number of set bits (set_bit) is satisfied.
- Use the bits of
- If additional bits need to be set after using all possible bits from
num1, set the least significant bits inres.
- Start with
-
Return the result:
- The constructed number (
res) minimizes the XOR value withnum1and satisfies the set bit condition.
- The constructed number (
Complexity
-
Time Complexity:
\(O(\log(\text{max}(num1, num2)))\)- Counting set bits and iterating through bits of
num1are logarithmic in the value of the number.
- Counting set bits and iterating through bits of
-
Space Complexity:
\(O(1)\)- No additional data structures are used; the space usage is constant.
Code
class Solution:
def minimizeXor(self, num1: int, num2: int) -> int:
res = 0
set_bit = 0
x, y = num1, num2
# Count the number of set bits in num2
while y > 0:
set_bit += (y & 1)
y = y >> 1
# Find the leftmost bit of num1
left_most_bit_num1 = 1
while x > 1:
x = x >> 1
left_most_bit_num1 = left_most_bit_num1 << 1
# Set bits in res using num1's bits
res = 0
while set_bit > 0 and left_most_bit_num1 > 0:
if left_most_bit_num1 & num1 == left_most_bit_num1:
res = res | left_most_bit_num1
set_bit -= 1
left_most_bit_num1 = left_most_bit_num1 >> 1
# Set remaining bits from the least significant position
curr = 1
while set_bit > 0:
if res & curr != curr:
res = res | curr
set_bit -= 1
curr = curr << 1
return res
Editorial
Trick
To check if the i-th bit of num is set:
Shift 1 left by i (1 << i) positions to isolate the i-th bit.
Perform a bitwise AND: num & (1 << i).
If the result is not 0, the i-th bit of num is set.
----------------------------------------------------------
To set the i-th bit of num:
Shift 1 left by i (1 << i) positions to isolate the i-th bit.
Perfom a bitwise OR: num | (1 << i).
----------------------------------------------------------
To unset the i-th bit of num:
Shift 1 left by i (1 << i) positions to create a mask.
Invert the mask using ~(1 << i) to make the i-th bit 1 and all the other bits 0.
Perform a bitwise AND: num & ~(1 << i).
Approach 1: From Optimal to Valid
class Solution:
def minimizeXor(self, num1: int, num2: int) -> int:
# Initialize result to num1. We will modify result.
result = num1
target_set_bits_count = bin(num2).count("1")
set_bits_count = bin(result).count("1")
# Start with the least significant bit (bit 0).
current_bit = 0
# Add bits to result if it has fewer set bits than the target.
while set_bits_count < target_set_bits_count:
# If the current bit in result is not set (0), set it to 1.
if not self._is_set(result, current_bit):
result = self._set_bit(result, current_bit)
set_bits_count += 1
# Move to the next bit.
current_bit += 1
# Remove bits from result if it has more set bits than the target.
while set_bits_count > target_set_bits_count:
# If the current bit in result is set (1), unset it (make it 0).
if self._is_set(result, current_bit):
result = self._unset_bit(result, current_bit)
set_bits_count -= 1
# Move to the next bit.
current_bit += 1
return result
# Helper function to check if the given bit position in result is set (1).
def _is_set(self, x: int, bit: int) -> bool:
return (x & (1 << bit)) != 0
# Helper function to set the given bit position in result to 1.
def _set_bit(self, x: int, bit: int):
return x | (1 << bit)
# Helper function to unset the given bit position in x (set it to 0).
def _unset_bit(self, x: int, bit: int):
return x & ~(1 << bit)