LeetCode Entry

1072. Flip Columns For Maximum Number of Equal Rows

22.11.2024 medium 2024 kotlin rust

Max same-bit-rows after flipping columns in 01-2D matrix

1072. Flip Columns For Maximum Number of Equal Rows medium blog post substack youtube deep-dive 1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/808

Problem TLDR

Max same-bit-rows after flipping columns in 01-2D matrix #medium #matrix

Intuition

Let’s observe what’s happening:


    // 0 0 0   ---
    // 0 0 1   ff- or --f   <-- mask
    // 1 1 0   ff- or --f
    // 1 1 1   ---
    //   v
    // 0 0 1
    // 0 0 0
    // 1 1 1
    // 1 1 0
    //     *
    //
    // 0 1 0
    // 0 1 1
    // 1 0 0
    // 1 0 1
    //   *    <-- intermediate column flips are irrelevant

    // 0 0 0 0 0 *
    // 1 1 1 1 1 *
    // 0 0 0 0 1  *
    // 1 1 1 1 0  *
    // 0 0 0 1 1   *     <-- symmetry
    // 1 1 1 0 0   *     <-- symmetry
    // 0 0 1 1 1    *
    // 1 1 0 0 0    *
    // 0 1 1 1 1     *
    // 1 0 0 0 0     *

Some observations:

  • intermediate flips are irrelevant, only pattern-flips can improve the situation
  • each row has a pattern and this pattern has a symmetry with its inverted version
  • the pattern and its inversion forms a groups, group size is the answer

Approach

  • one trick to collapse pattern with its inversion is to xor each with the first bit (@lee’s brain idea)
  • in Kotlin, simple groupBy works faster than strings hashes
  • in Rust [u8] key is faster than [u128, u128, u128], or [u64; 5] keys
  • c++ has bitset built-in

Complexity

  • Time complexity: \(O(nm)\)

  • Space complexity: \(O(nm)\)

Code


    fun maxEqualRowsAfterFlips(matrix: Array<IntArray>) =
        matrix.groupBy { r -> r.map { it xor r[0] }}
        .maxOf { it.value.size }


    pub fn max_equal_rows_after_flips(matrix: Vec<Vec<i32>>) -> i32 {
        *matrix.iter().fold(HashMap::new(), |mut hm, r| {
            *hm.entry(r.iter().map(|&b| r[0] ^ b).collect::<Vec<_>>())
            .or_insert(0) += 1; hm
        }).values().max().unwrap() as i32
    }


    int maxEqualRowsAfterFlips(vector<vector<int>>& m) {
        unordered_map<bitset<300>, int>c; int r = 0;
        for (auto v: m) {
            bitset<300>b;
            for (int i = 0; i < size(v);) b[i] = v[0] ^ v[i++];
            r = max(r, ++c[b]);
        }
        return r;
    }