└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | # 40 Important Bit Manipulation Interview Questions in 2025
2 |
3 |
4 |
5 |
6 |
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 |
822 |
823 |
824 |
825 |
--------------------------------------------------------------------------------