Set the Leftmost Unset Bit


This article seeks a method for setting a given number's leftmost unset bit. The first unset bit after the most significant set bit is considered the leftmost unset bit.

Problem Statement

Given a number n, the task is to set the left most bit of the binary expansion of the number that is unset. All the other bits should be left unchanged. If all the bits of the original number are already set, return the number.

Examples

Input: 46
Output: 62

Explanation

Binary Expansion of 46 = 101110.

Left most unset bit is 101110.

Upon setting the underlined bit we get, 111110. This is the binary expansion of 62.

Hence answer is 62.

Input: 11
Output: 15

Explanation

Binary Expansion of 11 = 1011.

Left most unset bit is 1011.

Upon changing the underlined bit, we get 1111 which is the binary expansion of 15.

Input: 30
Output: 31

Explanation

Binary Expansion of 30 = 11110.

Left most unset bit is 11110.

Upon setting the leftmost unset bit, we get 11111 which is the binary expansion of 31.

Input: 7
Output: 7

Explanation

Binary Expansion of 7 = 111.

Since all the bits are set, there is no left most unset bit. Hence the answer remains the same as the original number.

Solution Approach

  • Check if all the bits are set. If yes, then return the original number as the answer.

  • Find the position of the latest unset bit using bitwise AND operator, and update the counter.

  • Set the bit corresponding to the counter.

  • Display the answer.

To Find if All the Bits Are Set

The idea here is that by adding one bit, the input number will become a perfect square of 2 if all of its bits are set. Hence, the following expression will determine whether or not all the bits of the number are set: n & (n + 1) == 0;

Let us understand this through an example.

Let the number be 5. We need to check if all the bits of 5 are set or not.

n = 3 n + 1 = 4 n & (n + 1)
011 100 000

Thus it is safe to conclude that all the bits of n are already set and we return the number as it is.

To Find the Leftmost Unset Bit

If the output of the AND operation is not equal to zero, we proceed to find the leftmost unset bit. Start by generating a number with the number of bits equal to that of the given integer. Only the leftmost bit of the new number is set initially.

Then, we run a loop that starts with the leftmost 1 bit and searches for the first 0 going right by doing a bitwise AND between the given number and the new number. When the result of the AND operation is 0, we return the position, pos, of the first leftmost bit that is not set.

To Set the Leftmost Unset Bit

Generate a new number in which only the bit corresponding to pos is set. Perform bitwise OR operation between this new number and the original number.

Algorithm

Function all_bits_set()

  • Compute n & (n + 1).

  • If result == 0, return true.

  • Else return false.

Function find_leftmost_unset_bit()

  • Initialize m = 1, pos = 0.

  • while (n > m)

    • Left shift m by 1

  • Right shift m by 1 so that it corresponds to the most significant bit of n.

  • while ((n & m) != 0)

    • Right shift m by 1

    • pos++

  • As soon as the loop breaks, we have the position of the leftmost unset bit from the MSB.

  • Return log2(n) - pos which is the bit position from LSB.

Function set_leftmost_unset_bit()

  • Initialize k = 1

  • Function Call find_leftmost_unset_bit().

  • k = k << pos

  • Compute n | k.

  • Update n.

Function main()

  • Initialize n

  • Function Call all_bits_set()

  • Function Call find_leftmost_unset_bit()

  • Function Call set_leftmost_unset_bit()

  • Display n

Example: Programs

This programs modify an input number n by setting the leftmost unset bit of its binary expansion to 1. It employs bitwise operators OR as well as left shift and right shift operators and the bitwise AND operator to achieve its goal.

#include <stdio.h>
#include <math.h>

// function to check if all bits of the given number are already set
// if all bits of n are set, n + 1 will be a power of 2.
int all_bits_set(int n) {
   if ((n & (n + 1)) == 0) {
      return 1;
   }
   return 0;
}

// function to find the position of the leftmost unset bit from the LSB.
int find_leftmost_unset_bit(int n) {
   int m = 1, pos = 0;
   while (n > m) {
      m = m << 1;
   }
   m = m >> 1;
    
   while ((n & m) != 0) {
      m = m >> 1;
      pos++;
   }
    
   return (int)(log2(n) - pos);
}

// function to set the leftmost unset bit from the LSB.
void set_leftmost_unset_bit(int *n) {
   int k = 1;
   int pos = find_leftmost_unset_bit(*n);
   k = k << pos;
   *n = *n | k;
}

// main function
int main() {
   int n = 46;
   printf("Input Number: %d\n", n);
    
   if (all_bits_set(n)) {
      printf("%d\n", n);
      return 0;
   }
    
   set_leftmost_unset_bit(&n);
   printf("Number after setting the Leftmost Unset Bit: %d\n", n);
   return 0;
}

Output

Input Number: 46
Number after setting the Leftmost Unset Bit: 62
// A C++ program to set the left most unset bit of a number. If all the bits of the given number are already set, it returns the number as it is.
#include <iostream>
#include <cmath>
using namespace std;
// function to check if all bits of the given number are already set
// if all bits of n are set, n + 1 will be a power of 2.
bool all_bits_set(int n){
   if ((n & (n + 1)) == 0)    {
      return true;
   }
   return false;
}

// function to find the position of the leftmost unset bit from the LSB.
int find_leftmost_unset_bit(int n){
   int m = 1, pos = 0;
   while (n > m){
      m = m << 1;
   }
   m = m >> 1; // to make the number of digits in m equal to number of digits in n
   
   // the following loop executes till the first zero is encountered, starting from the msb
   while ((n & m) != 0){
      m = m >> 1;
      pos++;
   }
   
   // since pos is the position of the unset bit from the MSB we return log2(n) - pos which is the location of the leftmost unset bit from the LSB.
   return log2(n) - pos;
}

// function to set the leftmost unset bit from the LSB.
void set_leftmost_unset_bit(int &n){
   int k = 1;
   int pos = find_leftmost_unset_bit(n);
   k = k << (pos); // left shift k by pos
   n = n | k; // to set the leftmost unset bit
}

// main function
int main(){
   int n = 46;
   cout << "Input Number: "<< n << endl;
   if (all_bits_set(n))    {
      cout << n << endl;
      return 0;
   }
   set_leftmost_unset_bit(n);
   cout << "Number after setting the Leftmost Unset Bit: " << n << endl; // display the updated number
   return 0;
}

Output

Input Number: 46
Number after setting the Leftmost Unset Bit: 62
public class Main {
   // function to check if all bits of the given number are already set
   // if all bits of n are set, n + 1 will be a power of 2.
   static boolean allBitsSet(int n) {
      return (n & (n + 1)) == 0;
   }

   // function to find the position of the leftmost unset bit from the LSB.
   static int findLeftmostUnsetBit(int n) {
      int m = 1, pos = 0;
      while (n > m) {
         m = m << 1;
      }
      m = m >> 1;

      while ((n & m) != 0) {
         m = m >> 1;
         pos++;
      }

      return (int) (Math.log(n) / Math.log(2) - pos);
   }

   // function to set the leftmost unset bit from the LSB.
   static int setLeftmostUnsetBit(int n) {
      int k = 1;
      int pos = findLeftmostUnsetBit(n);
      k = k << pos;
      n = n | k;
      return n;
   }

   // main function
   public static void main(String[] args) {
      int n = 46;
      System.out.println("Input Number: " + n);

      if (allBitsSet(n)) {
         System.out.println(n);
      } else {
         n = setLeftmostUnsetBit(n);
         System.out.println("Number after setting the Leftmost Unset Bit: " + n);
      }
   }
}

Output

Input Number: 46
Number after setting the Leftmost Unset Bit: 62
import math

# function to check if all bits of the given number are already set
# if all bits of n are set, n + 1 will be a power of 2.
def all_bits_set(n):
   if (n & (n + 1)) == 0:
      return True
   return False

# function to find the position of the leftmost unset bit from the LSB.
def find_leftmost_unset_bit(n):
   m = 1
   pos = 0
   while n > m:
      m = m << 1
   m = m >> 1
    
   while (n & m) != 0:
      m = m >> 1
      pos += 1
        
   return int(math.log2(n) - pos)

# function to set the leftmost unset bit from the LSB.
def set_leftmost_unset_bit(n):
   k = 1
   pos = find_leftmost_unset_bit(n)
   k = k << pos
   n = n | k
   return n

# main function
if __name__ == "__main__":
   n = 46
   print("Input Number:", n)
    
   if all_bits_set(n):
      print(n)
   else:
      n = set_leftmost_unset_bit(n)
      print("Number after setting the Leftmost Unset Bit:", n)

Output

Input Number: 46
Number after setting the Leftmost Unset Bit: 62

Time and Space Analysis

Time Complexity − O(log2(n)), as in the function find_leftmost_unset_bit(), we may have to traverse all the log2(n) digits of the binary expansion to find the leftmost unset bit.

Space Complexity − O(1), as constant space is always used in the implementation.

Conclusion

This article discusses an approach to find and set the leftmost unset bit of a given number. If all the bits of the number were already set, we returned the number as it is. Else to set the said bit, we employed the use of the bitwise left shift and right shift operator to generate a new bit pattern and the bitwise OR operator to compute the result. The concept of the solution approach, multiple examples, the algorithm used, the C++ program solution as well as the time and space complexity analysis was explained thoroughly for a deeper understanding.

Updated on: 27-Oct-2023

191 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements