- 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
Odious Number
A number is considered to be an odious number if it has an odd number of 1s in its binary expansion. The first 10 odious numbers are 1,2,4,7,10,11,13,14,16,19,21. Interestingly, all powers of 2 are odious since they have only 1 set bit.
The following article discusses 2 approaches in detail to find whether a number is an odious number or not.
Problem Statement
This problem aims to check whether the given number is an odious number i.e. it is a positive number with an odd number of set bits in its binary expansion.
Examples of Odious Number
Input: 34
Output: Non-Odious Number
Explanation
Binary representation of 34 is 10010.
Number of set bits = 2.
Since the number of 1s is even, 34 is not an odious number.
Input: 1024
Output: Odious Number
Explanation
Binary representation of 1024 is 10000000000.
Number of set bits = 1.
Since 1024 is a power of 2, there is only 1 set bit. Hence it is an odious number.
Input: 53
Output: Non-Odious Number
Explanation
(53)10 = (110101)2
Number of set bits = 4.
Hence it is not an odious number.
Solution Approach
In order to determine if a number is odious or not, we must know whether the number of set bits is odd or even. The main task here is to count the number of set bits in the binary expansion of the number. The following techniques can be employed to count the number of bits and then check if the result is odd or even.
Naive Approach
Go through all the bits of the number, one by one, using a loop and a right shift operator.
If the bit value is 1, increment count by one.
Check if the final value of count is odd or even.
Display the answer.
Pseudocode
Function no_of_set_bits()
Initialise count = 0
while (n > 0)
if ((n & 1) > 0) Increment count Right Shift n
return count
Function is_odious()
if (count is odd)
return true
else
return false
Function main()
Initialise n
Function call no_of_set_bits()
Function call is_odious()
Print output
Example: C++ Program
The program checks whether a number is odious or not. It examines the right most bit in every iteration of the loop by right shifting the value of n at the end of each iteration in the function no_of_set_bits().
#include<iostream> using namespace std; // this function counts the number of set bits by analyzing the rightmost bit using a while loop till n > 0. // it performs logical & operation between 1 and n to determine if the rightmost bit is set or not. // if it is set, count is incremented by 1 // right shift the value of n to make the bit left of the rightmost bit, the new rightmost bit. int no_of_set_bits(int n){ int count = 0; while (n > 0){ // if the rightmost bit is 1: increment count if ((n & 1) > 0){ count++; } // right shift the value of n to examine the next bit n = n >> 1; } return count; } // this function determines if count of set bits is odd or even // odd -> odious bool is_odious(int count){ // if count is odd return true if (count % 2 != 0){ return true; } return false; } // main function int main(){ int n = 27; int countBits = no_of_set_bits(n); if (is_odious(countBits)){ cout << n << " is Odious Number"; } else { cout << n << " is Non-Odious Number"; } return 0; }
Output
27 is Non-Odious Number
Analysis of Time and Space
Time Complexity: O(log(n)), since binary expansion of n takes log2n bits and we examine all the bits to check for set bits.
Space Complexity: O(1) , as no extra space is used.
Brian Kernighan’s Algorithm Approach
This algorithm can be employed to count the number of set bits for a number in a more efficient way. Function is_odious() can then be used to determine whether the number is odious.
The fundamental principle of this approach is to repeatedly clear the number's rightmost set bit while keeping track of how many iterations are needed to get to zero. The steps involved are −
Initialise count to 0
While the number is greater than zero, perform bitwise & between the number and its 2’s complement to unset the rightmost set bit.
Increment count with each iteration of the loop.
Check whether the final count is odd.
Display the result.
Example
Let the number be 10. The binary expansion of 10 is 1010. It can be observed that it has 2 set bits.
Loop iteration 1 −
n = 10 n & (n-1) = 10 & 9 1010 (n) 1001 (n - 1) 1000 (n = 8)
Loop iteration 2 −
n = 8 n & (n-1) = 8 & 7 1000 (n) 0111 (n-1) 0 (n = 0)
Number of iterations = Number of set bits = 2.
Pseudocode
Function no_of_set_bits()
Initialise count = 0
while (n > 0)
n = n & (n-1)
Increment count
return count
Function is_odious()
Same as in the previous approach
Function main()
Same as in the previous approach
Example: C++ Program
This program counts the number of set bits by counting the number of iterations needed to unset all the set bits. To unset the bits, we perform bitwise & between n and n - 1. This works because the binary expression for n-1 flips the rightmost set bit of n as well as all bits that follow it.
#include<iostream> using namespace std; // this function counts the number of set bits by unsetting the rightmost set bit using a while loop till n > 0. // it performs logical & operation between n and n - 1 to unset the rightmost set bit. // count is incremented in every iteration int no_of_set_bits(int n){ int count = 0; while (n > 0){ // update the value of n to unset the current rightmost set bit n = n & (n - 1); count++; } return count; } // this function determines if count of set bits is odd or even // odd -> odious bool is_odious(int count){ // if count is odd return true if (count % 2 != 0){ return true; } return false; } // main function int main(){ int n = 27; int countBits = no_of_set_bits(n); // function call if (is_odious(countBits)){ cout << n << " is Odious Number"; } else { cout << n << " is Non-Odious Number"; } return 0; }
Output
27 is Non-Odious Number
Time and Space Analysis
Time Complexity − O(log(x)), where x is the number of set bits in the number. If there is only 1 set bit, the loop will run once.
Space Complexity − O(1) , as no extra space is used.
Comparing the Above Approaches
While the first approach is fairly easy to understand, it takes log(n) iterations to produce the final result. The second approach, on the other hand, takes log(x) iterations, where x is the number of set bits in the binary expansion of the number. Hence, it improves the performance.
Conclusion
This article discusses two approaches to check whether a number is odious. It also provides us with the concept of the approach, examples, algorithm used, C++ program solution as well as the complexity analysis of each method. It also draws comparison between the two approaches to figure out which one is more efficient.