- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
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.