Minimize XOR

Med
#2213Time: O(1), as the loops run a fixed number of times (at most 31, for 32-bit integers), making the runtime constant.Space: O(1), as we only use a few variables to store counts and the result, regardless of the input size.

Prompt

Given two positive integers num1 and num2, find the positive integer x such that:

  • x has the same number of set bits as num2, and
  • The value x XOR num1 is minimal.

Note that XOR is the bitwise XOR operation.

Return the integer x. The test cases are generated such that x is uniquely determined.

The number of set bits of an integer is the number of 1's in its binary representation.

 

Example 1:

3 XOR 3 = 0

Example 2:

3 XOR 1 = 2

 

Constraints:

  • 1 <= num1, num2 <= 109

Approaches

2 approaches with complexity analysis and trade-offs.

This approach is based on a greedy strategy that considers three separate cases based on the comparison between the number of set bits in num1 and num2. The goal is to construct x by making decisions that minimize x XOR num1 at each step, tailored to each specific case.

Algorithm

  • Calculate bits1 = Integer.bitCount(num1) and bits2 = Integer.bitCount(num2).
  • Case 1: bits1 == bits2
    • The optimal x is num1 itself, as num1 XOR num1 = 0, which is the minimum possible XOR value. Return num1.
  • Case 2: bits2 > bits1
    • To minimize the XOR value, x should be as similar to num1 as possible. Start with x = num1.
    • We need to set an additional diff = bits2 - bits1 bits in x.
    • To cause the smallest increase in x XOR num1, set these bits at the least significant positions where num1 has a 0.
    • Iterate from i = 0 to 30. If the i-th bit of num1 is 0, set the i-th bit in x and decrement diff until diff is 0.
  • Case 3: bits2 < bits1
    • To minimize the XOR value, x must match the most significant set bits of num1.
    • Initialize x = 0.
    • We need to set bits2 bits in x.
    • Iterate from i = 30 down to 0. If the i-th bit of num1 is 1, set the i-th bit in x and decrement a counter for the bits we need to set. Stop when the counter reaches 0.
  • Return the constructed x.

Walkthrough

First, we calculate the number of set bits for num1 and num2, let's call them bits1 and bits2 respectively. The logic then branches into three distinct scenarios:

  1. bits1 == bits2: To make x XOR num1 minimal (i.e., 0), x must be equal to num1. Since x would then have bits1 set bits, which is equal to the required bits2, this is the optimal solution. So, x = num1.

  2. bits2 > bits1: We need x to have more set bits than num1. To keep x as close to num1 as possible, we start by setting x = num1. This ensures all the original set bits of num1 are matched, minimizing the most significant part of the XOR result. Then, we need to set bits2 - bits1 additional bits. To cause the smallest increase in the XOR value, we should set these bits at the least significant available positions. We iterate from the least significant bit (LSB) upwards, and for each position i where num1 has a 0, we set the i-th bit in x until we have set the required number of additional bits.

  3. bits2 < bits1: We need x to have fewer set bits than num1. To minimize the XOR result, we must prioritize matching the most significant set bits of num1. We construct x from scratch (x=0). We iterate from the most significant bit (MSB) downwards. If the i-th bit is set in num1, we set the i-th bit in x and decrement our count of needed bits. We stop after we have set bits2 bits in x. This ensures x is composed of the bits2 most significant bits of num1.

class Solution {    public int minimizeXor(int num1, int num2) {        int bits1 = Integer.bitCount(num1);        int bits2 = Integer.bitCount(num2);        int x = 0;         if (bits1 == bits2) {            return num1;        } else if (bits2 > bits1) {            x = num1;            int diff = bits2 - bits1;            for (int i = 0; i <= 30 && diff > 0; i++) {                if ((num1 & (1 << i)) == 0) {                    x |= (1 << i);                    diff--;                }            }        } else { // bits2 < bits1            int count = bits2;            for (int i = 30; i >= 0 && count > 0; i--) {                if ((num1 & (1 << i)) != 0) {                    x |= (1 << i);                    count--;                }            }        }        return x;    }}

Complexity

Time

O(1), as the loops run a fixed number of times (at most 31, for 32-bit integers), making the runtime constant.

Space

O(1), as we only use a few variables to store counts and the result, regardless of the input size.

Trade-offs

Pros

  • Logically straightforward, breaking the problem down into understandable sub-problems.

  • Correct and efficient for the given constraints.

Cons

  • The code is slightly more verbose due to the explicit branching for the three cases.

  • The logic is split, whereas a more elegant, unified solution exists.

Solutions

class Solution {public  int minimizeXor(int num1, int num2) {    int cnt = Integer.bitCount(num2);    int x = 0;    for (int i = 30; i >= 0 && cnt > 0; --i) {      if ((num1 >> i & 1) == 1) {        x |= 1 << i;        --cnt;      }    }    for (int i = 0; cnt > 0; ++i) {      if ((num1 >> i & 1) == 0) {        x |= 1 << i;        --cnt;      }    }    return x;  }}

Video walkthrough

Newsletter

One sharp idea, every week

System design and interview prep — short enough to finish.

No spam. Unsubscribe anytime.

Practice

Same difficulty — related problems to reinforce the pattern.