Skip to content
dsa450for five year olds

Bit Manipulation · 7 of 10

Copy set bits in a range

Look through a window over the bits of N, and switch on the same bits in M wherever N has a 1.

Simple way
time O(R - L + 1)
room O(1)
Clever way
time O(1)
room O(1)

The problem, simply

You get two numbers, M and N, and a window of positions from L to R. Positions are counted from 1, starting at the rightmost bit.

For every position inside the window where N has a 1, make that bit of M a 1 too. Never turn a bit of M off, and never touch bits outside the window. Give back the new M.

A story to remember it

Picture it

bits
012345M = 43101011N = 59111011

M = 43 and N = 59. The window is positions 2 to 5, which are bits 1 to 4 in the drawing because the drawing counts from 0. Inside the window N has 1s at bits 1, 3 and 4.

  • path

Examples

A normal case

In
M = 10, N = 13, L = 2, R = 3
Out
14

M is 1010 and N is 1101. In positions 2 and 3, N has a 0 and then a 1. So position 3 of M turns on: 1110 = 14.

Small window at the right end

In
M = 8, N = 7, L = 1, R = 2
Out
11

N has 1s at positions 1 and 2. M was 1000, so it becomes 1011 = 11. The 1 at position 3 of N is outside the window and is ignored.

Some bits are already on

In
M = 43, N = 59, L = 2, R = 5
Out
59

N has 1s at positions 2, 4 and 5. M already has positions 2 and 4 on, so only position 5 is new. M goes from 101011 to 111011 = 59.

Nothing to copy

In
M = 5, N = 8, L = 1, R = 3
Out
5

N is 1000. Its only 1 is at position 4, outside the window. M stays 5.

The whole number

In
M = 0, N = -1, L = 1, R = 32
Out
-1

The window covers all 32 bits, so M becomes a copy of N's 1s, which is all 32 bits on. A careless mask gets this wrong (see below).

Way 1: the simple way

Walk through the window one position at a time.

  1. For each position i from L to R, make a one bit number bit = 1 << (i - 1).
  2. If N & bit is not 0, N has a 1 there, so do M = M | bit.
  3. Give back M.
java
class Solution {
    public static int copySetBits(int m, int n, int l, int r) {
        for (int i = l; i <= r; i++) {
            int bit = 1 << (i - 1);      // positions start at 1, shifts start at 0
            if ((n & bit) != 0) {
                m |= bit;                // switch on the same light in M
            }
        }
        return m;
    }
}

How long it takes: one step per position in the window, O(R - L + 1), which is at most 32 steps. Extra room: O(1).

Way 2: the clever way

Make the cardboard first: a number called a mask, with 1s exactly on positions L to R and 0s everywhere else. Then two bit operations finish the job.

  1. (1 << R) - 1 has 1s on positions 1 to R. Taking 1 away from a lone 1 bit turns on every bit below it.
  2. (1 << (L - 1)) - 1 has 1s on positions 1 to L - 1, the part we must cut away.
  3. XOR the two to keep only positions L to R. That is the mask.
  4. N & mask keeps only the 1s of N that show through the hole.
  5. M | (N & mask) switches those on in M and leaves every other bit alone.

Cut the stencil, then copy through it

01 / 07

bits
012345M = 43101011N = 59111011

M = 43 and N = 59. The window is positions 2 to 5, counting from 1 on the right. In the drawing, bits are counted from 0, so that is bits 1 to 4.

  • checking
  • done
  • answer
  • rejected
  • path
  • just added
  • ignored
java
class Solution {
    public static int copySetBits(int m, int n, int l, int r) {
        long upTo = (1L << r) - 1;          // ones on positions 1 to r
        long below = (1L << (l - 1)) - 1;   // ones on positions 1 to l - 1
        long mask = upTo ^ below;           // ones on positions l to r only
        return (int) (m | (n & mask));      // copy N's ones through the hole
    }
}

How long it takes: a fixed handful of bit operations, O(1). Extra room: one mask, O(1).

Watch out for

  • Off by one. Positions in this problem start at 1, but shifts start at 0. Position i is 1 << (i - 1).
  • Using ^ or = instead of | when copying. The problem says only switch on. XOR would switch off the bits that are on in both.
  • Forgetting the cut. (1 << R) - 1 alone also copies positions below L.

What interviewers ask next

  • Copy the window exactly, zeros too? Clear the window in M first, then OR: (M & ~mask) | (N & mask). This is how you write a field into a packed number.
  • Toggle all bits of M in the range? M ^ mask.
  • Clear all bits of M in the range? M & ~mask.
  • Another way to build the mask? ((1L << (R - L + 1)) - 1) << (L - 1): a run of R - L + 1 ones, slid up to position L.
  • Check whether all bits in the range are on in N? (N & mask) == mask.

Remember this

Grown-up words: the cardboard with the hole is a bit mask, looking through it is bitwise AND, switching lights on is bitwise OR, and cutting away the lower part is XOR of two masks.