Skip to content

Commit 9b98aa5

Browse files
authored
Update brain_teasers.md
1 parent c8dba94 commit 9b98aa5

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

notes/brain_teasers.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,15 @@ Below is a detailed comparison of commonly used sorting algorithms:
250250
- It’s important to **understand the data** when selecting a sorting algorithm. Factors such as the size of the dataset, its distribution, and the data type being sorted can significantly influence the choice of algorithm.
251251
- If the **stability requirement** is important, meaning the relative order of equal elements must be preserved, you should opt for stable sorting algorithms like Merge Sort or Tim Sort.
252252
- When memory is a concern, **in-place sorting** algorithms, such as Quick Sort or Heap Sort, are preferable because they require minimal additional memory.
253-
- Consider the **time complexity trade-offs** when choosing a sorting algorithm. While Quick Sort is generally fast, its performance can degrade to \( O(n^2) \) in the worst case if not implemented carefully.
253+
- Consider the **time complexity trade-offs** when choosing a sorting algorithm. While Quick Sort is generally fast, its performance can degrade to $O(n^2)$ in the worst case if not implemented carefully.
254254
- **Hybrid approaches** like Tim Sort, which combines Merge Sort and Insertion Sort, are designed to optimize performance by leveraging the strengths of multiple sorting techniques.
255255

256256
### Practical Applications
257257

258258
- **Merge Sort** is particularly useful for sorting linked lists since it does not require random access to the elements.
259259
- **Quick Sort** is often chosen for general-purpose sorting due to its efficiency in the average case and its ability to sort in-place.
260260
- **Counting Sort** and **Radix Sort** are effective when sorting integers within a known and limited range, offering linear-time complexity under the right conditions.
261-
- **Heap Sort** is a good option when memory usage is restricted and a guaranteed \( O(n \log n) \) time complexity is necessary.
261+
- **Heap Sort** is a good option when memory usage is restricted and a guaranteed $O(n \log n)$ time complexity is necessary.
262262
- **Insertion Sort** is ideal for very small datasets or as a subroutine in more complex algorithms due to its simplicity and efficiency on nearly sorted data.
263263

264264
## Bit Manipulation
@@ -267,18 +267,18 @@ Bit manipulation involves algorithms that operate directly on bits, the basic un
267267

268268
### Fundamental Concepts
269269

270-
- A solid grasp of **binary representation** is essential for working with bitwise operations. In binary, each digit (or bit) represents a power of 2, starting with the least significant bit (LSB) on the right, which corresponds to \( 2^0 \), and increasing as you move left.
270+
- A solid grasp of **binary representation** is essential for working with bitwise operations. In binary, each digit (or bit) represents a power of 2, starting with the least significant bit (LSB) on the right, which corresponds to $2^0$, and increasing as you move left.
271271
- **Signed and unsigned integers** differ in how they represent numbers. **Unsigned integers** can only represent non-negative values, while **signed integers** use the most significant bit (MSB) as a sign bit, with 0 representing positive numbers and 1 representing negative numbers, typically using two's complement representation.
272272
- **Bitwise operators** are key tools for manipulating individual bits. The **AND (`&`)** operator produces 1 only when both corresponding bits are 1, making it useful for masking bits. The **OR (`|`)** operator sets a bit to 1 if at least one of the corresponding bits is 1, often used for setting bits.
273273
- The **XOR (`^`)** operator produces 1 when the bits are different, useful for toggling bits or swapping values. The **NOT (`~`)** operator flips all bits, performing a bitwise negation.
274274
- The **left shift (`<<`)** operation shifts bits to the left, filling with zeros from the right, effectively multiplying the number by powers of two. Conversely, **right shift (`>>`)** operations shift bits to the right, with two variations: **logical shifts**, which fill with zeros from the left (used for unsigned integers), and **arithmetic shifts**, which preserve the sign bit, used for signed integers.
275275

276276
### Bit Manipulation Techniques
277277

278-
- To **set a bit** at position \( n \) to 1, the operation `number |= (1 << n)` can be used. This works by left-shifting 1 by \( n \) positions to create a mask with only the \( n \)-th bit set, and then applying bitwise OR to modify the original number.
279-
- To **clear a bit** at position \( n \), use the operation `number &= ~(1 << n)`. Here, 1 is left-shifted by \( n \) and negated to form a mask where only the \( n \)-th bit is 0, and applying bitwise AND clears that bit.
280-
- To **toggle a bit** at position \( n \), the operation `number ^= (1 << n)` is used. By left-shifting 1 by \( n \) and applying XOR, the target bit at \( n \) is flipped.
281-
- To **check if a bit** at position \( n \) is set to 1, the operation `(number & (1 << n)) != 0` is employed. It works by left-shifting 1 by \( n \) and applying bitwise AND; a non-zero result indicates the bit is set.
278+
- To **set a bit** at position $n$ to 1, the operation `number |= (1 << n)` can be used. This works by left-shifting 1 by $n$ positions to create a mask with only the $n$-th bit set, and then applying bitwise OR to modify the original number.
279+
- To **clear a bit** at position $n$, use the operation `number &= ~(1 << n)`. Here, 1 is left-shifted by $n$ and negated to form a mask where only the $n$-th bit is 0, and applying bitwise AND clears that bit.
280+
- To **toggle a bit** at position $n$, the operation `number ^= (1 << n)` is used. By left-shifting 1 by $n$ and applying XOR, the target bit at $n$ is flipped.
281+
- To **check if a bit** at position $n$ is set to 1, the operation `(number & (1 << n)) != 0` is employed. It works by left-shifting 1 by $n$ and applying bitwise AND; a non-zero result indicates the bit is set.
282282
- To **clear the least significant bit (LSB)**, the operation `number &= (number - 1)` is effective. Subtracting 1 flips all bits from the LSB onward, and applying AND clears the lowest set bit.
283283
- To **isolate the least significant bit**, the operation `isolated_bit = number & (-number)` is used. In two’s complement, `-number` is the bitwise complement plus one, so ANDing it with `number` isolates the LSB.
284284
- To **count the set bits** (Hamming weight) in a number, Kernighan's Algorithm is applied using the following code:
@@ -317,7 +317,7 @@ This sequence of XOR operations swaps the values of `a` and `b` without needing
317317

318318
- **Left shifting** (`<<`) is a useful technique for **multiplying by powers of two**. For instance, `number << 3` multiplies `number` by \(2^3 = 8\), which is a fast alternative to regular multiplication.
319319
- Similarly, **right shifting** (`>>`) can be used for **dividing by powers of two**. For example, `number >> 2` divides `number` by \(2^2 = 4\), making it an efficient way to handle division for unsigned integers or logical shifts.
320-
- To **extract specific bits** from a number, you can use a combination of shifting and masking. For instance, to extract bits from position \( p \) to \( p + n - 1 \), the operation `(number >> p) & ((1 << n) - 1)` can be applied. This shifts the target bits to the right and uses a mask to isolate only those bits.
320+
- To **extract specific bits** from a number, you can use a combination of shifting and masking. For instance, to extract bits from position $p$ to $p + n - 1$, the operation `(number >> p) & ((1 << n) - 1)` can be applied. This shifts the target bits to the right and uses a mask to isolate only those bits.
321321

322322
### Cautions and Best Practices
323323

0 commit comments

Comments
 (0)