Skip to main content
Back to problems
#3499
Medium Algorithms

Maximize active section with trade i

String Enumeration
31.2% acceptance
Feb 25, 2026
69
28
You are given a binary string s of length n, where: '1' represents an active section. '0' represents an inactive section. You can perform at most one trade to maximize the number of active sections in s. In a trade, you: Convert a contiguous block of '1's that is surrounded by '0's to all '0's. Afterward, convert a contiguous block of '0's that is surrounded by '1's to all '1's. Return the maximum number of active sections in s after making the optimal trade. Note: Treat s as if it is augmented with a '1' at both ends, forming t = '1' + s + '1'. The augmented '1's do not contribute to the final count.

Solution

Rust
Time O(n²)
Space O(n)
LeetCode
solution.rs
impl Solution {
  pub fn max_active_sections_after_trade(s: String) -> i32 {
    let _n = s.len();
    let b = s.as_bytes();
    // Count initial active sections
    let base = b.iter().filter(|&&c| c == b'1').count() as i32;
    // Trade: find a block of 1s surrounded by 0s (or augmented 1s), convert to 0s.
    // Then find a block of 0s surrounded by 1s (or augmented), convert to 1s.
    // Treat t = "1" + s + "1". Find zero-blocks and one-blocks in t.
    // A zero-block in t at position [i..j] is surrounded by 1s (since t has 1s at ends and valid structure).
    // A one-block in t (not counting the augmented ends) is [i..j] surrounded by 0s.
    // Trade: pick a one-block B1 surrounded by zeros, convert to zeros.
    // Then the surrounding zeros might form a larger zero-block.
    // Actually: after converting B1 to zeros, we get a larger zero-block. Then convert that to ones.
    // Net gain: (size of new zero-block) - (original zero-block size we used).
    // The blocks in t = "1"+s+"1":
    // Alternating zero-blocks and one-blocks.
    // Segments of 0s in t are the places we can convert.
    // Strategy: 
    // 1. Find all zero-runs Z1, Z2, ... in t (adjacent ones separate them).
    // 2. Each one-run O1, O2, ... (in t, ignoring augmented ends) between consecutive zero-runs.
    // 3. If we convert O_k (surrounded by Z_k and Z_{k+1}) to zeros, we merge Z_k, O_k, Z_{k+1}.
    //    New zero-run size = len(Z_k) + len(O_k) + len(Z_{k+1}).
    //    Then we convert this new zero-run to ones.
    //    Net gain = len(new zero-run) - len(O_k) = len(Z_k) + len(Z_{k+1}).
    //    (We gain Z_k + Z_{k+1} new ones, but lose 0 active sections since O_k was already active.)
    //    Wait: O_k was active (all 1s). Converting to 0s: lose len(O_k). Then converting new zero-run to 1s: gain len(Z_k)+len(O_k)+len(Z_{k+1}). Net = len(Z_k)+len(Z_{k+1}).
    //    But augmented ends' O-blocks can't be traded (they're not "in" s).
    // Build segments in t = "1" + s + "1"
    let t: Vec<u8> = std::iter::once(b'1').chain(b.iter().copied()).chain(std::iter::once(b'1')).collect();
    let tn = t.len();
    // Find alternating blocks
    let _zero_runs: Vec<usize> = vec![];
    let _one_runs: Vec<usize> = vec![]; // only interior one-runs (not augmented)
    // Track: t starts with 1, so first block is 1-block (augmented).
    let mut i = 0;
    let _in_augmented_start = true;
    let mut segments: Vec<(u8, usize)> = vec![];
    while i < tn {
      let c = t[i];
      let mut j = i;
      while j < tn && t[j] == c { j += 1; }
      segments.push((c, j - i));
      i = j;
    }
    // segments[0] = ('1', ...) augmented start.
    // segments[last] contains augmented end '1'.
    let max_gain = if segments.len() < 3 {
      0
    } else {
      // For each interior one-run (segments[1], segments[3], ...):
      // Gain = adjacent zero-runs' lengths.
      let mut best = 0i32;
      for idx in (2..segments.len()-1).step_by(2) {
        // segments[idx] should be a '1' run (interior)
        if segments[idx].0 != b'1' { continue; }
        // Adjacent zero-runs: segments[idx-1] and segments[idx+1]
        if idx == 0 || idx + 1 >= segments.len() { continue; }
        if segments[idx-1].0 != b'0' || segments[idx+1].0 != b'0' { continue; }
        let gain = (segments[idx-1].1 + segments[idx+1].1) as i32;
        if gain > best { best = gain; }
      }
      best
    };
    base + max_gain
  }
}