Rust for Algorithmic Problem-Solving

Bit Manipulation

Bit manipulation uses bitwise operators (&, |, ^, !, <<, >>) and hardware bit intrinsics (count_ones, trailing_zeros, leading_zeros, next_power_of_two) to represent subsets as integer bitmasks, perform branchless arithmetic, and solve XOR parity problems in $O(1)$ register operations.

8-Bit Subset Bitmask: `mask = 0b0010_1100` (Represents the set `{2, 3, 5}`)

  - Check if element `k` is in set:   `(mask & (1 << k)) != 0`
  - Add element `k` to set:           `mask |= 1 << k`
  - Remove element `k` from set:      `mask &= !(1 << k)`
  - Toggle element `k`:               `mask ^= 1 << k`
  - Clear lowest set bit (`2`):       `mask &= mask - 1`  --> `0b0010_1000`
  - Isolate lowest set bit (`1<<2`):  `mask & mask.wrapping_neg()` --> `0b0000_0100`

Note on Bitwise NOT in Rust (! Instead of ~)

Unlike C/C++/Python (which use ~x for bitwise NOT and !x for logical NOT), Rust uses !x for both bitwise NOT on integers (!0u32 == 0xFFFF_FFFF) and logical NOT on booleans (!true == false)!

Built-In Hardware Bit Methods on Rust Integers

Every unsigned integer type (u8, u16, u32, u64, u128, usize) provides portable methods that compile directly to single-cycle CPU instructions:

Rust Method Example (0b0010_1100u8) Result Algorithmic Application
x.count_ones() 44u8.count_ones() 3 Size of subset represented by bitmask (POPCNT).
x.trailing_zeros() 44u8.trailing_zeros() 2 Index of the smallest element in the bitmask (TZCNT).
x.leading_zeros() 44u8.leading_zeros() 2 Fast integer $\lfloor\log_2(x)\rfloor = \text{BITS} - 1 - x.\text{leading_zeros}()$ (LZCNT).
x.is_power_of_two() 32u32.is_power_of_two() true Checks x > 0 && (x & (x - 1)) == 0.
x.next_power_of_two() 20usize.next_power_of_two() 32 Sizing Segment Trees and hash tables to powers of two.
x.ilog2() 44u32.ilog2() 5 Exact floor base-2 logarithm ($\lfloor\log_2(44)\rfloor = 5$).

Iterating Over All Submasks of a Bitmask in $O(3^k)$ Time

In Bitmask Dynamic Programming (where $N \le 20$ elements are represented as a u32 mask), iterating over every non-empty submask sub of a given mask uses the classic bitwise decrement trick sub = (sub - 1) & mask, visiting only valid subsets of mask in $O(3^N)$ total time across all masks (instead of $O(4^N)$!):

/// Returns all non-empty submasks of `mask` in descending order using `sub = (sub - 1) & mask`.
pub fn collect_submasks(mask: u32) -> Vec<u32> {
    let mut submasks = Vec::new();
    let mut sub = mask;
    while sub > 0 {
        submasks.push(sub);
        sub = (sub - 1) & mask;
    }
    submasks
}

/// Finds the single number that appears an odd number of times in `nums` in O(n) time, O(1) space
/// using the XOR self-inverse property (`x ^ x == 0` and `x ^ 0 == x`).
pub fn find_single_number(nums: &[u64]) -> u64 {
    nums.iter().fold(0u64, |acc, &x| acc ^ x)
}

/// Iterates over the set bit indices of `mask` in O(count_ones) steps!
pub fn set_bit_indices(mut mask: u64) -> Vec<u32> {
    let mut indices = Vec::with_capacity(mask.count_ones() as usize);
    while mask != 0 {
        let lowest_bit_idx = mask.trailing_zeros();
        indices.push(lowest_bit_idx);
        mask &= mask - 1; // Clear lowest set bit in 1 instruction
    }
    indices
}

fn main() {
    let mask = 0b1011u32; // Bits 0, 1, and 3 (3 bits -> 2^3 - 1 = 7 non-empty submasks)
    let subs = collect_submasks(mask);
    assert_eq!(subs.len(), 7);

    let unique = find_single_number(&[42, 7, 99, 7, 42]);
    assert_eq!(unique, 99);

    let bits = set_bit_indices(0b1010_0100);
    assert_eq!(bits, vec![2, 5, 7]);

    println!(
        "Submasks of 0b1011: {} items, unique XOR element: {unique}, set bit indices: {bits:?}",
        subs.len()
    );
}
Submasks of 0b1011: 7 items, unique XOR element: 99, set bit indices: [2, 5, 7]