└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # 40 Important Bit Manipulation Interview Questions in 2025 2 | 3 |
4 |

5 | 6 | data-structures-and-algorithms 7 | 8 |

9 | 10 | #### You can also find all 40 answers here 👉 [Devinterview.io - Bit Manipulation](https://devinterview.io/questions/data-structures-and-algorithms/bit-manipulation-interview-questions) 11 | 12 |
13 | 14 | ## 1. What is a _Bit_? 15 | 16 | The term **"bit"** stems from "binary" and "digit." As the basic unit of information in computing and digital communications, a bit can assume one of two values: 0 or 1. 17 | 18 | ### Binary System vs Decimal System 19 | 20 | Computers operate using a **binary number system**, employing just two numerals: 0 and 1. In contrast, our day-to-day decimal system is **base-10**, utilizing ten numerals (0-9). 21 | 22 | In the binary system: 23 | - **Bit**: Represents 0 or 1 24 | - **Nibble**: Comprises 4 bits, representing 16 values (0-15 in decimal) 25 | - **Byte**: Contains 8 bits, representing 256 values (0-255 in decimal) 26 | 27 | For instance, the decimal number 5 is depicted as $0101_2$ in binary. 28 | 29 | ### Bit Manipulation 30 | 31 | Bits are pivotal in **bit manipulation**, a field encompassing operations like bit shifting, logical operations (AND, OR, XOR), and bit masking. These techniques find applications in data compression, encryption, and device control. 32 | 33 | Considering two 8-bit numbers: $0010\,1010$ and $0000\,1100$. The logical AND operation gives: 34 | 35 | $$ 36 | \begin{array}{c c c c c c c c c} 37 | & 0 & 0 & 1 & 0 & 1 & 0 & 1 & 0 \\ 38 | \text{AND} & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 0 \\ 39 | \hline 40 | & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 41 | \end{array} 42 | $$ 43 | 44 | ### Integer Representation in Bits 45 | 46 | An integer's representation typically occupies a **fixed** number of bits. On many systems, an integer uses **32 bits**. Thus, a 32-bit signed integer spans $-2^{31}$ to $2^{31} - 1$. 47 | 48 | ### Hardware Considerations 49 | 50 | Although **bits** underpin computing, hardware designs can constrain their usage. A 32-bit CPU processes 32 bits simultaneously, requiring extra steps for larger numbers. This led to the adoption of "**double words**" and "**quad words**" to represent larger integers. 51 |
52 | 53 | ## 2. What is a _Byte_? 54 | 55 | A **byte** is a foundational data unit in computing and telecommunications, capable of representing 256 unique values, ranging from 0 to 255. It consists of 8 **bits**, the smallest data storage units, which can be either 0 or 1. 56 | 57 | ### Bit Composition 58 | 59 | Each bit in a byte has a place value, starting from the least significant bit (LSB) on the right to the most significant bit (MSB) on the left. Their place values are: 60 | 61 | | Place Value | Bit Position | 62 | |-------------|--------------| 63 | | 128 | 7 | 64 | | 64 | 6 | 65 | | 32 | 5 | 66 | | 16 | 4 | 67 | | 8 | 3 | 68 | | 4 | 2 | 69 | | 2 | 1 | 70 | | 1 | 0 | 71 | 72 | 73 | Setting all bits to 1 yields the byte's maximum value of 255. 74 | 75 | ### Converting Bytes to Decimal 76 | 77 | To find the decimal equivalent of a byte, sum the place values of bits set to 1. For a byte with all bits as 1: 78 | 79 | $$ 80 | 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255 81 | $$ 82 | 83 | ### Code Example: Byte to Decimal Conversion 84 | 85 | Here is the Python code: 86 | 87 | ```python 88 | def byte_to_decimal(byte_str): 89 | # Reverse the string for right-to-left calculation 90 | byte_str = byte_str[::-1] 91 | 92 | # Sum up place values for bits set to 1 93 | return sum(int(byte_str[i]) * 2 ** i for i in range(len(byte_str))) 94 | 95 | # Example usage 96 | byte_value = "11111111" # All bits are 1 97 | decimal_value = byte_to_decimal(byte_value) 98 | print(decimal_value) # Output: 255 99 | ``` 100 |
101 | 102 | ## 3. Explain what is a _Bitwise Operation_. 103 | 104 | **Bitwise operations** are actions applied to individual bits within binary numbers or data units like integers. These operations offer several advantages, including speed and memory efficiency, and are widely used in specific computing scenarios. 105 | 106 | ### Why Use Bitwise Operations? 107 | 108 | - **Speed**: Executing bitwise operations is often faster than using standard arithmetic or logical operations. 109 | 110 | - **Memory Efficiency**: Operating at the bit level allows the storage of multiple flags or small integers within a single data unit, optimizing memory usage. 111 | 112 | - **Low-Level Programming**: These operations are crucial in embedded systems and microcontroller programming. 113 | 114 | - **Data Manipulation**: Bitwise operations can selectively alter or extract specific bits from a data unit. 115 | 116 | ### Types of Operators 117 | 118 | #### Logical Operators 119 | 120 | 1. **AND (`&`)**: Yields `1` if corresponding bits are both `1`; otherwise, `0`. 121 | - Example: `5 & 3 = 1`. 122 | 123 | 2. **OR (`|`)**: Yields `1` if one or both corresponding bits are `1`; otherwise, `0`. 124 | - Example: $5 | 3 = 7$. 125 | 126 | 3. **XOR (`^`)**: Yields `1` when corresponding bits differ; otherwise, `0`. 127 | - Example: $5 \oplus 3 = 6$. 128 | 129 | 4. **NOT (`~`)**: Inverts all bits. 130 | - Example: $~5$ becomes $-6$ in 2's complement. 131 | 132 | #### Shift Operators 133 | 134 | 1. **Left Shift (`<<`)**: Moves bits to the left and fills in with `0`. 135 | - Example: $5 \text{ << 2 } = 20$. 136 | 137 | 2. **Right Shift (`>>`)**: Moves bits to the right and fills in based on the sign of the number. 138 | - Example: $5 \text{ >> 2 } = 1$. 139 | 140 | 3. **Zero Fill Right Shift (>>>)**: Shifts bits right, filling in zeros. 141 | - Example: $-5 \text{ >>> 2 } = 1073741823$. 142 | 143 | #### Specialized Operations 144 | 145 | - **Ones' Complement**: Similar to NOT but restricted to 32 bits. 146 | - Example: `(~5) & 0xFFFFFFFF`. 147 | 148 | - **Twos' Complement**: Used for representing negative numbers in two's complement arithmetic. 149 | - Example: $~5 + 1 = -6$. 150 | 151 | ### Practical Applications 152 | 153 | - **Flag Management**: Bits can represent on/off flags, and bitwise operators can be used to toggle these. 154 | 155 | - **Data Compression**: These operations play a role in compression algorithms. 156 | 157 | - **Encryption**: Bitwise manipulation is used in cryptographic algorithms. 158 | 159 | ### Code Example: Flag Manipulation 160 | 161 | Here is the Python code: 162 | 163 | ```python 164 | # Define flags with binary representation 165 | FLAG_A, FLAG_B, FLAG_C, FLAG_D = 0b0001, 0b0010, 0b0100, 0b1000 166 | 167 | # Set flags B and D 168 | flags = FLAG_B | FLAG_D 169 | 170 | # Check if Flag C is set 171 | print("Flag C is set" if flags & FLAG_C else "Flag C is not set") 172 | ``` 173 |
174 | 175 | ## 4. What are some real-world applications of _Bitwise Operators_? 176 | 177 | **Bitwise operators** provide efficient means of manipulating variables at the bit level. This feature is integral to various applications like data compression, cryptography, and embedded systems. 178 | 179 | ### Real-World Use-Cases 180 | 181 | #### Data Compression Algorithms 182 | 1. **Run-Length Encoding**: Identical consecutive characters are stored once followed by a count. This requires bitwise operators to efficiently manage the bit stream. 183 | 2. **Huffman Coding**: For implementing lossless data compression, this technique assigns shorter codes to frequently occurring characters, which is made possible through bitwise operations. 184 | 185 | #### Cryptography and Data Security 186 | 1. **Bit Level Encryption**: Techniques like XORing bits are used in various encryption algorithms. 187 | 2. **Hardware Security**: In integrated chips, bitwise operations play a crucial role in providing secure key management systems. 188 | 189 | #### Network Packet Analysis 190 | 1. **Packet Inspection**: Applications, especially in firewalls and routers, might necessitate bitwise operations for quick and low-level packet analysis. 191 | 192 | #### Embedded Systems 193 | 1. **Peripheral Configuration**: The individual bits in control registers, often set using bitwise operations, help configure peripherals in microcontrollers and other embedded systems. 194 | 2. **Memory Mapped I/O**: Bitwise operations are instrumental in interfacing with embedded hardware through memory-mapped I/O. 195 | 196 | #### Algorithm Optimization 197 | 1. **Bit Manipulation for Speed**: In specific situations, using bit-level operations can significantly enhance the efficiency of algorithms. This is especially true for resource-constrained devices. 198 | 2. **Integer Multiplication and Division in Limited-Bit Environments**: On systems with limitations on the size of numbers that can be represented, bit manipulation can be used to carry out basic arithmetic operations more efficiently. 199 | 200 | #### Graphics and Image Processing 201 | 1. **Pixel Manipulation**: Adjusting color information or applying specific transformations may involve bitwise operations in image processing. 202 | 2. **Optimized Blending**: Quick and optimized alpha blending, common in graphic rendering, can be achieved using bitwise operations without the need for costly division and multiplication. 203 | 204 | #### Data Integrity and Validation 205 | 1. **Flags in Data Structures**: Bitwise operations enable data integrity checks and the management of multiple flags within data structures while using limited memory. 206 | 2. **Parity Checks**: Detection of odd/even parity in small data segments, commonly in error-checking algorithms, employs bitwise methods. 207 | 208 | #### Memory Optimization and Cache Management 209 | 1. **Memory Allocation**: In scenarios where individual bits are used for encoding specific information within memory allocation strategies, bitwise operations are fundamental. 210 | 2. **Cache Optimization**: Techniques like bit masking can be used to optimize cache performance by ensuring data alignment with cache lines. 211 | 212 | #### User Interface and Input Management 213 | 1. **Keyboard Input Handling**: In certain contexts, handling multiple keyboard inputs or mapping specific keys can be simplified using bit manipulation. 214 | 2. **Graphics Display**: To save resources while still effectively managing color palettes in limited environments, bit manipulation is employed. 215 | 216 | #### Dynamic Resource Management 217 | 1. **Memory and Resource Allocation**: In operating systems and embedded systems, bitwise operations provide a means of managing the allocation and deallocation of resources with precision and efficiency. 218 | 219 | #### General Efficiency and Resource Utilization 220 | 1. **Memory Efficiency**: Bit fields in languages like C and C++ make efficient use of memory by grouping variables into compact memory units. 221 | 2. **Performance Enhancement in Math Operations**: Bit manipulation can be used for efficient multiplication, division, and modulo operations on binary integers. 222 | 3. **Finding Mismatches and Duplicates**: Bitwise Exclusive OR (XOR) operations ascertain duplicates or mismatches in data sets. 223 | 224 | ### Code Example: Run-Length Encoding 225 | 226 | Here is the Python code: 227 | 228 | ```python 229 | def run_length_encode(data): 230 | encoded = [] 231 | count = 1 232 | for i in range(1, len(data)): 233 | if data[i] == data[i - 1]: 234 | count += 1 235 | else: 236 | encoded.append((data[i - 1], count)) 237 | count = 1 238 | encoded.append((data[-1], count)) 239 | return encoded 240 | 241 | def run_length_decode(encoded): 242 | decoded = "" 243 | for char, count in encoded: 244 | decoded += char * count 245 | return decoded 246 | 247 | # Test the Run-Length Encoding and Decoding 248 | input_data = "AAABBCCCCDDEEEE" 249 | encoded_data = run_length_encode(input_data) 250 | decoded_data = run_length_decode(encoded_data) 251 | print("Original Data:", input_data) 252 | print("Encoded Data:", encoded_data) 253 | print("Decoded Data:", decoded_data) 254 | ``` 255 | 256 | In this example, the input string "AAABBCCCCDDEEEE" is run-length encoded and then decoded back to its original form using bit manipulation techniques. 257 |
258 | 259 | ## 5. What is a _bitwise AND_ operation and how can it be used to check if a number is _odd_ or _even_? 260 | 261 | The **bitwise AND** operation is a fundamental concept in computer science and cryptography. When you apply this operation to two bits, the result is 1 if both bits are 1. At least one bit being 0 results in a zero output. This operation is often used in hashing and encryption algorithms. 262 | 263 | In the context of determining whether a number is **odd** or **even**, the bitwise AND operation becomes useful. 264 | 265 | ### Bitwise AND to Check for Odd or Even 266 | 267 | The basic way to figure out if a decimal number is even or odd, based on its binary representation, is to look at the least significant bit (the rightmost bit): 268 | 269 | - If that bit is 1, the number is odd. 270 | - If it's 0, the number is even. 271 | 272 | The rule behind this method is that all even numbers end in `0` in binary, and odd numbers end in `1`. 273 | 274 | ### Logical Representation 275 | 276 | - bitwise AND with 1: Returns 1 if rightmost bit is 1 (indicating odd number), and 0 if it's 0 (indicating even number). 277 | 278 | #### Mathematical Foundation 279 | 280 | When you do a **bitwise AND** with a number and 1, you get: 281 | 282 | - 1 if both the numbers are 1. 283 | - 0 if the other number is 0. 284 | 285 | For an even number $n$, its **binary** form ends in `0`. When you take the **logical AND** with `1`, you actually perform a **logical AND** with `0`, which results in `0`. 286 | 287 | For an odd number $n$, its **binary** form ends in `1`. When you take the **logical AND** with `1`, the operation returns `1`. 288 | 289 | ### Example 290 | 291 | - For n = 5 (binary: 101): 292 | 293 | `5 & 1` gives 1, indicating `n` is odd. 294 | 295 | - For n = 10 (binary: 1010): 296 | 297 | `10 & 1` gives 0, indicating `n` is even. 298 | 299 | ### Python Code 300 | 301 | Here is the Python code for the operation: 302 | 303 | ```python 304 | def is_odd(n): 305 | return n & 1 == 1 306 | ``` 307 | 308 | The function `is_odd` checks whether `n` is an odd number by using bitwise AND with 1. If the result is 1, the number is odd. 309 |
310 | 311 | ## 6. Explain the _bitwise OR_ operation with an example. 312 | 313 | The **Bitwise OR** operator works at the binary level. It combines two bit sequences. For each position, if **either bit is 1**, the result has a 1 in that position. 314 | 315 | ### Key Insight 316 | 317 | - **Input**: Two binary numbers, say `a = 1010` and `b = 1100`. 318 | - **Output**: Their bitwise OR, denoted by `a | b`, gives `1110`. 319 | 320 | ### Code Example: Implementing Bitwise OR 321 | 322 | Here is the Python code: 323 | 324 | ```python 325 | a = 10 # Binary: 1010 326 | b = 12 # Binary: 1100 327 | 328 | result = a | b 329 | print(bin(result)) # Output: 0b1110 (14 in decimal) 330 | ``` 331 |
332 | 333 | ## 7. How does the _bitwise XOR_ operation work, and what is it commonly used for? 334 | 335 | The **bitwise XOR operator** (\^\) compares each bit of two integers, setting the resulting bit to 1 only when the two input bits are different. 336 | 337 | ### XOR in Action 338 | 339 | - **Example**: 5 ($101$) $\text{XOR}$ 3 ($011$) = 6 ($110$) 340 | 341 | - **Properties**: Commutative: $A \text{ XOR } B = B \text{ XOR } A$ 342 | 343 | ### Practical Applications 344 | 345 | - **Invert Elements and Undo Pairing**: Useful for error checking and data identification. 346 | 347 | - **Text/Data Encryption**: Employed in ciphers that use bit manipulation for security. 348 | 349 | - **Efficiently Swapping Values**: Useful for in-place memory operations without using temporary storage. 350 | 351 | - **Color Calculations and Image Processing**: Commonplace in graphics processing for tasks like filtering. 352 | 353 | - **Error Correction in Data Transmission**: Ensures data integrity during communication. 354 | 355 | - **Modifying Individual Bits in a Register**: Efficiently flip specific bits without affecting others. 356 | 357 | ### Code Example: Swapping Numbers 358 | 359 | Here is the Python code: 360 | 361 | ```python 362 | a, b = 5, 7 363 | a = a ^ b 364 | b = a ^ b 365 | a = a ^ b 366 | print(a, b) # Output: 7, 5 367 | ``` 368 |
369 | 370 | ## 8. Demonstrate how to set, toggle, and clear a _specific bit_ in a number using _bitwise operators_. 371 | 372 | Let's first discuss the different bitwise operations: 373 | 374 | - **Setting a Bit** involves turning the bit on (to 1), if it's not already. 375 | 376 | - **Toggling a Bit** changes the bit's state: 1 becomes 0, and vice versa. 377 | 378 | - **Clearing a Bit**, on the other hand, turns the bit off (to 0). 379 | 380 | And here is the table of operations: 381 | 382 | | Bit State | Operations | Result | 383 | |-----------|-------------|--------| 384 | | 0 | Set | 1 | 385 | | 0 | Toggle | 1 | 386 | | 0 | Clear | 0 | 387 | | 1 | Set | 1 | 388 | | 1 | Toggle | 0 | 389 | | 1 | Clear | 0 | 390 | 391 | 392 | 393 | ### Bit Manipulation Operations 394 | 395 | Here is the code: 396 | 397 | In C++: 398 | 399 | ```cpp 400 | #include 401 | 402 | // Set the I-th bit of N 403 | int setBit(int N, int I) { 404 | return N | (1 << I); 405 | } 406 | 407 | // Toggle the I-th bit of N 408 | int toggleBit(int N, int I) { 409 | return N ^ (1 << I); 410 | } 411 | 412 | // Clear the I-th bit of N 413 | int clearBit(int N, int I) { 414 | return N & ~(1 << I); 415 | } 416 | 417 | int main() { 418 | int number = 10; // 0b1010 in binary 419 | int bitPosition = 1; 420 | 421 | // Set bit in position bitPosition 422 | int newNumber = setBit(number, bitPosition); // Result: 14 (0b1110) 423 | std::cout << "Number after setting bit: " << newNumber << std::endl; 424 | 425 | // Toggle bit in position bitPosition 426 | newNumber = toggleBit(newNumber, bitPosition); // Result: 10 (0b1010) 427 | std::cout << "Number after toggling bit: " << newNumber << std::endl; 428 | 429 | // Clear bit in position bitPosition 430 | newNumber = clearBit(newNumber, bitPosition); // Result: 8 (0b1000) 431 | std::cout << "Number after clearing bit: " << newNumber << std::endl; 432 | 433 | return 0; 434 | } 435 | ``` 436 | 437 | ### Visual Illustration 438 | 439 | Here are the steps visually: 440 | 441 | #### Setting a Bit 442 | 443 | ```plaintext 444 | Initial Number: 1010 (10 in decimal) 445 | Bit Position: 1 446 | Shifted 1 to: 0010 447 | Result (OR): 1110 (14 in decimal) 448 | ``` 449 | 450 | #### Toggling a Bit 451 | 452 | ```plaintext 453 | Previous Result: 1110 (14 in decimal) 454 | Bit Position: 1 455 | Shifted 1 to: 0010 456 | Result (XOR): 1010 (10 in decimal) 457 | ``` 458 | 459 | #### Clearing a Bit 460 | 461 | ```plaintext 462 | Previous Result: 1010 (10 in decimal) 463 | Bit Position: 1 464 | Shifted Negation: 1101 465 | Logical AND: 1000 (8 in decimal) 466 | ``` 467 |
468 | 469 | ## 9. What is _bit masking_, and how would you create a _mask_ to isolate the _nth bit_? 470 | 471 | **Bit masking** involves using **bitwise operations** to either clear or set specific bits in a binary number. 472 | 473 | For instance, if you want to extract the 3rd bit of a number, you would use the **bit mask** `00001000` (in binary), which is decimal 8. 474 | 475 | ### Creating a Bit Mask to Isolate the $n^{th}$ Bit 476 | 477 | To extract the $n^{th}$ bit from a number `num`, you can use a bit mask that has all 0s except for a 1 at the $n^{th}$ position. 478 | 479 | You can generate this bit mask `mask` by left-shifting a 1 by $n-1$ positions. If $n=3$, for example, the resultant `mask` would be 4 in decimal or `00000100` in binary. 480 | 481 | Here's an example, using $n=3$: 482 | 483 | ```python 484 | def extract_nth_bit(num, n): 485 | mask = 1 << (n-1) 486 | return (num & mask) >> (n-1) 487 | ``` 488 | 489 | ### Mask Action: Logical AND 490 | 491 | To **extract** the bit, you perform a **logical AND** of the number with the mask. All bits in `mask` are zero, except for the $n^{th}$ bit, which preserves the corresponding bit in the original number. All other bits become zero. 492 | 493 | ### Mask Action: Bit Shift (Right) 494 | 495 | After using the **logical AND**, the extracted bit is still in position 1 ($2^1$). By shifting it to the right one time, it will be in position 0 ($2^0$), i.e., as 0 or 1. 496 | 497 | ### Code Example: Extracting $3^{rd}$ Bit 498 | 499 | ```python 500 | def extract_nth_bit(num, n): 501 | mask = 1 << (n-1) 502 | return (num & mask) >> (n-1) 503 | 504 | # Using a number where the 3rd bit is 1 505 | num = 13 # 1101 in binary 506 | print(extract_nth_bit(num, 3)) # Output: 1 507 | ``` 508 |
509 | 510 | ## 10. Explain how _left_ and _right shifts_ (_<<_ and _>>_) work in bit manipulation. 511 | 512 | **Bit shifts**, controlled by the `<<` (left) and `>>` (right) operators, move bits in a binary number. Each shift direction and position has unique behavior. 513 | 514 | ### Direction vs. Operator 515 | 516 | - **Direction**: Determines whether bits shift to the left or to the right. 517 | - **Operator**: Symbolizes the actual shift in the code. 518 | 519 | 520 | ### Shift Direction and Unary Operators 521 | 522 | - **Left Shift** (<<): Moves bits to the right, effectively multiplying the number by $2^n$. 523 | - **Right Shift** (>>): Moves bits to the left and truncates the remainder, akin to integer division by $2^n$ in most programming languages. 524 | 525 | ### Shift Operations on Binary Numbers 526 | 527 | Let's understand shift operations through examples: 528 | 529 | ```plaintext 530 | Original Number (in binary): 11001010 531 | ``` 532 | 533 | #### Right Shift ($\text{>>}$) 534 | 535 | - 1-bit Right Shift 536 | ```plaintext 537 | 1100101 538 | Binary: 1100101 539 | Decimal: 105 540 | ``` 541 | 542 | - 2-bit Right Shift 543 | ``` 544 | 110010 545 | Binary: 110010 546 | Decimal: 50 547 | ``` 548 | 549 | - 3-bit Right Shift 550 | ``` 551 | 11001 552 | Binary: 11001 553 | Decimal: 25 554 | ``` 555 | 556 | - 4-bit, full 8-bit, and 10-bit Right Shift 557 | All shift operations are readily achieved by further bit truncation. 558 | 559 | **Note**: As your task requires involving multiplication and division, such shift operations lead to an understanding of these mathematical operations in binary number representation. 560 | 561 | - Multiplication 562 | By performing a left shift, you are essentially multiplying the number by 2. 563 | 564 | ``` 565 | 110010 566 | Binary: 1100100 567 | Decimal: 100 568 | ``` 569 | 570 | - Division 571 | Right shifts are akin to dividing a number by powers of 2. A 3-bit right shift divides the given number by $2^3 = 8$ . 572 | 573 | ```plaintext 574 | 13/2^3 = 13/8 = 1, remainder = 5 575 | Based on this example: 576 | 11010 577 | Binary: 11010 578 | Decimal: 26 579 | ``` 580 | 581 | ### Code Example: Right Shift to Divide by 2 582 | 583 | Here is the Python code: 584 | 585 | ```python 586 | number = 8 587 | right_shifted = number >> 1 # This effectively divides by 2 588 | print(right_shifted) # Output will be 4 589 | ``` 590 |
591 | 592 | ## 11. What is the difference between _>>_ and _>>>_ operators? 593 | 594 | Let's look at two shift operators defined in Java: the **right shift (>>) operator** and the **unsigned right shift (>>>) operator**, and compare their functionality. 595 | 596 | ### Understanding the Operators 597 | 598 | - **Right Shift (`>>`)**: Moves all bits of the specified numeric value to the right. It fills the leftmost bits with the sign bit (0 for positive, 1 for negative). 599 | 600 | - **Unsigned Right Shift (`>>>`)**: Similar to the `>>` operator, but it always fills the left-moved positions with zeros, ignoring the sign bit. 601 | 602 | ### Visual Representation 603 | 604 | ```plaintext 605 | Decimal Binary Bits 606 | 10 00001010 607 | 10 >> 1 00000101 - 5 608 | 10 >>> 1 00000101 - 5 609 | -------------------------- 610 | -10 11110110 611 | -10 >> 1 11111011 - (-5) 612 | -10 >>> 1 01111011 - 251 613 | ``` 614 |
615 | 616 | ## 12. Explain how to perform _left_ and _right bit rotations_. 617 | 618 | **Bit rotation** refers to shifting the bits of a binary number to the left or right, and wrapping the bits around so that any that "fall off" one end are reintroduced at the other. 619 | 620 | ### Arithmetic Shift vs Logical Shift 621 | 622 | In many programming languages, bit shifts are either arithmetic or logical. 623 | 624 | - **Arithmetic shifts** are typically used for signed integers and preserve the sign bit, which means the bit shifted in from the most significant bit becomes the new least significant bit, and bits "shifted off" on the other end are discarded. 625 | - **Logical shifts** shift all bits, including the sign bit, and always fill in the vacated bit positions with zeros. 626 | 627 | #### Code Example: Logical and Arithmetic Shifts 628 | 629 | Here is C++ code: 630 | 631 | ```cpp 632 | #include 633 | 634 | int main() { 635 | // Explain logical shift 636 | int logicalShiftResult = -16 >> 3; 637 | 638 | // Explain arithmetic shift 639 | int arithmeticShiftResult = -16 << 3; 640 | 641 | return 0; 642 | } 643 | ``` 644 |
645 | 646 | ## 13. Write a function that counts the number of _set bits_ (1s) in an _integer_. 647 | 648 | ### Problem Statement 649 | 650 | The task is to count the number of set bits in an integer - the **1**s in its binary representation. 651 | 652 | ### Solution 653 | 654 | One approach is to check each bit and sum them. An optimized solution uses a technique called **Brian Kernighan's Algorithm**. 655 | 656 | It is based on the observation that for any number `x`, the value of `x & (x-1)` has the bits of the rightmost set `1` unset. Hence, repeating this operation until the number becomes `0` yields the set bit count. 657 | 658 | #### Algorithm Steps 659 | 660 | 1. Initialize a count variable to `0`. 661 | 2. Iterate using a **while loop** until the number is `0`. 662 | 3. Within each iteration, decrement the number `n` by `n & (n-1)` and increment the `count` variable by `1`. 663 | 664 | #### Complexity Analysis 665 | 666 | - **Time Complexity**: $O(\text{{set bits count}})$, as it depends on the number of set bits. 667 | - **Space Complexity**: $O(1)$ 668 | 669 | #### Implementation 670 | 671 | Here is the Python code: 672 | 673 | ```python 674 | def count_set_bits(n): 675 | count = 0 676 | while n: 677 | n &= (n-1) 678 | count += 1 679 | return count 680 | ``` 681 | 682 | Here is the C++ code: 683 | 684 | ```cpp 685 | int countSetBits(int n) { 686 | int count = 0; 687 | while (n) { 688 | n &= (n - 1); 689 | count++; 690 | } 691 | return count; 692 | } 693 | ``` 694 |
695 | 696 | ## 14. Determine if a number is a _power of two_ using _bit manipulation_. 697 | 698 | ### Problem Statement 699 | 700 | The task is to design an algorithm that determines whether a given number is a **power of two**. 701 | 702 | ### Solution 703 | 704 | Using **bit manipulation**, we can apply the **logical AND** operator to swiftly identify powers of two. 705 | 706 | - If a number is a power of two, it has exactly one bit set in its binary representation. 707 | - Subtracting 1 from a power of two yields a binary number with all lower bits set. 708 | 709 | Combining these properties, we obtain an expression that performs the essential check. 710 | 711 | #### Algorithm Steps 712 | 713 | 1. Check if the number is **non-negative**. 714 | 2. Apply the **bitwise AND** operation between the number and its **one's complement** (the bitwise negation of the number). 715 | 3. Determine if the result is **zero**. 716 | 717 | If the result is zero, we confirm the number is a power of two. 718 | 719 | #### Complexity Analysis 720 | 721 | - **Time Complexity**: $O(1)$ 722 | - **Space Complexity**: $O(1)$ 723 | 724 | #### Implementation 725 | 726 | Here is the Python code: 727 | 728 | ```python 729 | def is_power_of_two(x: int) -> bool: 730 | return x > 0 and (x & (x-1)) == 0 731 | ``` 732 |
733 | 734 | ## 15. Design a function that adds two numbers without using the '+' operator. 735 | 736 | ### Problem Statement 737 | 738 | The task is to create a function that would add two numbers **without using the `+` operator**. 739 | 740 | ### Solution 741 | 742 | There are several methods to add two numbers without using the `+` operator, each with its own trade-offs. One common approach is to use **bit manipulation**. 743 | 744 | #### Algorithm Steps 745 | 746 | 1. **Perform XOR Operation**: 747 | - Calculate the bitwise XOR of the two numbers. This produces a number where the set bits represent the positions at which the two numbers have different bits. 748 | 749 | ``` 750 | 0010 (2) 751 | XOR 0100 (4) 752 | ------------ 753 | 0110 (6) 754 | ``` 755 | 756 | 2. **Perform AND Operation, then Left Shift**: 757 | - Perform bitwise AND of the two numbers and then left shift the result by `1`. This brings forward any 'carry' bits to the appropriate position. 758 | 759 | ``` 760 | 0010 (2) 761 | AND 0100 (4) 762 | ------------ 763 | 0000 (0) 764 | ``` 765 | 766 | After left shifting by 1: 767 | 768 | ``` 769 | 0000 (0) 770 | << 1 771 | ------------ 772 | 0000 (0) 773 | ``` 774 | 775 | 3. **Recursion**: Apply the addition method to the new **XOR** result and the **AND-left-shifted** result. The recursion continues until there are no carry bits left. 776 | 777 | ``` 778 | 0110 (XOR output) 779 | 0000 (Carry bits from AND-left-shifted operation) 780 | ``` 781 | 782 | Next, we perform the addition method to `0110` and `0000`, which returns `0110`. 783 | 784 | The final result will be `0110` which equals 6, the sum of 2 and 4. 785 | 786 | #### Complexity Analysis 787 | 788 | - **Time Complexity**: $O(\log n)$ where $n$ is the larger of the two numbers. 789 | - **Space Complexity**: $O(1)$ 790 | 791 | #### Implementation 792 | 793 | Here is the Python code: 794 | 795 | ```python 796 | def add_without_plus_operator(a, b): 797 | while b: 798 | # Calculate the carry bits 799 | carry = a & b 800 | 801 | # Use XOR to get the sum without carry 802 | a = a ^ b 803 | 804 | # Left shift the carry to add in the next iteration 805 | b = carry << 1 806 | 807 | return a 808 | 809 | # Test the function 810 | print(add_without_plus_operator(2, 4)) # Output: 6 811 | ``` 812 |
813 | 814 | 815 | 816 | #### Explore all 40 answers here 👉 [Devinterview.io - Bit Manipulation](https://devinterview.io/questions/data-structures-and-algorithms/bit-manipulation-interview-questions) 817 | 818 |
819 | 820 | 821 | data-structures-and-algorithms 822 | 823 |

824 | 825 | --------------------------------------------------------------------------------