Print numbers in the range 1 to n having bits in an alternate pattern


Alternate bit pattern implies the positioning of 0’s and 1’s in a number at an alternate position i.e. no two 0s or 1’s are together. For example, 10 in binary representation is (1010)2 which has an alternate bit pattern as 0’s and 1’s are separated by each other.

Problem Statement

Given an integer, N. Find all the integers in the range 1 to N where the bit pattern of the integer is alternating.

Example 1

Input: 10
Output: 1, 2, 5, 10

Explanation

$\mathrm{(1)_{10} = (1)_2, (2)_{10} = (10)_2, (5)_{10} = (101)_2, (10)_{10} = (1010)_2}$

Example 2

Input: 31
Output: 1, 2, 5, 10, 21

Explanation

$\mathrm{(1)_{10} = (1)_2, (2)_{10} = (10)_2, (5)_{10} = (101)_2, (10)_{10} = (1010)_2, (21)_{10} = (10101)_2}$

Approach 1: Check for Alternate Pattern

The naive approach to solve this problem would be to check for every number in the range 1 to n if it has bits in an alternate pattern or not.

This can be done as follows,

For checking if a number has an alternate bit pattern, we can use the truth table of the AND operation to check if consecutive bits are different.

Pseudocode −

procedure checkAltPattern (num)
   temp = num
   count = 0
   while (temp)
      count = count +1
      num = num >> 1
   end while
   for i = 0 to count - 2
      iTh = num >> i
      i2Th = num >> (i + 2)
      if ((iTh & 1) != (i2Th & 1))
         ans = FALSE
      end if
   end for
   ans = TRUE
end procedure

procedure numbers (num)
   ans []
   for i = 1 to num
      if checkAltPattern = TRUE
         ans.add(i)
      end if
   end for
end procedure

Example

In the following program, we check for every number in the range 1 to N if they have an alternate bit pattern by checking if, at every alternate position, the same bits are present or not.

#include <bits/stdc++.h>
using namespace std;
// Function to check if the number has alternate pattern
bool checkAltPattern(int num){
   int temp = num, count = 0;
   
   // Counting total bits of the number by using the right shift operator
   while (temp)    {
      count++;
      
      // Right shift of a number shift all the bits one position right
      temp >>= 1;
   }
   
   // For every alternate position checking if bits are same
   for (int i = 0; i < (count - 1); i++)    {
      int iTh = num >> i, i2Th = num >> (i + 2);
      
      // iTh & 1 gives the bit at ith position
      // i2Th &N1 gives the bit at (i+2)th position
      // If both bits are not same then bits pattern is not alternate
      if ((iTh & 1) != (i2Th & 1))        {
         return false;
      }
   }
   return true;
}
vector<int> numbers(int num){

   // Initializing an array to add numbers with alternate bit pattern
   vector<int> ans;
   for (int i = 1; i <= num; i++){
      if (checkAltPattern(i)){
         ans.push_back(i);
      }
   }
   return ans;
}
int main(){
   int N = 50;
   cout << "Numbers in range 1 to " << N << " having alternate bit pattern : ";
   vector<int> res = numbers(N);
   for (int i = 0; i < res.size(); i++){
      cout << res[i] << " ";
   }
   return 0;
}

Output

Numbers in range 1 to 50 having alternate bit pattern : 1 2 5 10 21 42

Time Complexity − O(nlogn) as the for each number we check for the alternate pattern which takes O(logn) time as logn is the number of bits used to represent that number. Thus total time is O(logn + logn + … n times) = O(nlogn)

Space Complexity − O(1) as no extra space is used.

Approach 2: Generate the Numbers From 1

An optimized and better approach to the problem would be to start with the first number having an alternate pattern and then consecutively alternately add 0s and 1s.

For adding 0 on the right side, use the left shift operator.

For adding 1 on the right side, use the left shift first and then add 1 using the XOR operator.

Pseudocode −

procedure addZero (pass)
   pass = pass << 1
   ans = pass
end procedure

procedure addOne (pass)
   pass = pass << 1
   pass = pass ^ 1
   ans = pass
end procedure

procedure numbers (N)
   ans []
   int num = 1
   ans.add (num)
   while (1)
      num = addZero (num)
      if (num > N)
         break
      else
         ans.add (num)
      end if
      num = addOne (num)
      if (num > N)
         break
      else
         ans.add (num)
      end if
   end while
end procedure

Example

In the following program, addZero() function adds 0 at the LSB position and addOne() function adds 1 at the LSB position.

#include <bits/stdc++.h>
using namespace std;
int addZero(int pass){
   // Left shift puts 0 at LSB position
   pass = pass << 1;
   return pass;
}
int addOne(int pass){

   // Left shift puts 0 at LSB position
   pass = pass << 1;
   
   // XOR with 1 sets the LSB position
   pass = pass ^ 1;
   return pass;
}
vector<int> numbers(int N){

   // Initializing an array to add numbers with alternate bit pattern
   vector<int> ans;
   
   // First number with alternate bit pattern is 1
   int num = 1;
   ans.push_back(num);
   while (1)    {
      num = addZero(num);
      
      // If on adding 0, num is greater than N then leave loop
      if (num > N)        {
         break;
      }
      else{
         ans.push_back(num);
      }
      num = addOne(num);
      
      // If on adding 1, num is greater than N then leave loop
      if (num > N){
         break;
      }
      else{
         ans.push_back(num);
      }
   }
   return ans;
}

int main(){
   int N = 50;
   cout << "Numbers in range 1 to " << N << " having alternate bit pattern : ";
   vector<int> res = numbers(N);
   for (int i = 0; i < res.size(); i++){
      cout << res[i] << " ";
   }
   return 0;
}

Output

Numbers in range 1 to 50 having alternate bit pattern : 1 2 5 10 21 42

Time Complexity − O(logn)

Space Complexity − O(1)

Conclusion

In conclusion, for finding the numbers with alternate bit pattern an optimised approach will be to produce numbers itself from 1 by left shifting and then setting and unsetting the LSB position. This approach is the most optimized and optimal.

Updated on: 28-Sep-2023

46 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements