title: 1-bit and 2-bit Characters
slug: one-bit-and-two-bit-characters
difficulty: easy
leetcode_id: 717
leetcode_url: https://leetcode.com/problems/1-bit-and-2-bit-characters/
categories:
  - arrays
patterns:
  - greedy

description: |
  We have two special characters:

  - The first character can be represented by one bit `0`.
  - The second character can be represented by two bits (`10` or `11`).

  Given a binary array `bits` that ends with `0`, return `true` if the last character must be a one-bit character.

constraints: |
  - `1 <= bits.length <= 1000`
  - `bits[i]` is either `0` or `1`.

examples:
  - input: "bits = [1,0,0]"
    output: "true"
    explanation: "The only way to decode it is two-bit character (10) and one-bit character (0). So the last character is one-bit character."
  - input: "bits = [1,1,1,0]"
    output: "false"
    explanation: "The only way to decode it is two-bit character (11) and two-bit character (10). So the last character is NOT a one-bit character."

explanation:
  intuition: |
    Imagine you're reading a coded message where each character is either a single `0` or a pair starting with `1` (`10` or `11`). Your job is to determine if the very last `0` in the array stands alone as its own character.

    The key insight is that **a `1` always consumes the next bit**. When you see a `1`, you must read two bits together as one character. When you see a `0`, it stands alone as a one-bit character.

    Think of it like this: walk through the array from left to right. Every time you encounter a `1`, skip ahead by 2 positions (you've consumed a two-bit character). Every time you encounter a `0`, skip ahead by 1 position (you've consumed a one-bit character).

    If this greedy decoding process lands you exactly on the last index, then that final `0` must be a standalone one-bit character. If you land past it (by skipping over it as part of a two-bit character), the answer is `false`.

  approach: |
    We solve this using a **Greedy Linear Scan**:

    **Step 1: Initialise the position pointer**

    - `i`: Set to `0` to start at the beginning of the array

    &nbsp;

    **Step 2: Iterate through the array (except the last element)**

    - While `i < len(bits) - 1` (we stop before the last element):
      - If `bits[i] == 1`: This starts a two-bit character, so jump ahead by 2 (`i += 2`)
      - If `bits[i] == 0`: This is a one-bit character, so jump ahead by 1 (`i += 1`)

    &nbsp;

    **Step 3: Check the final position**

    - After the loop, check if `i == len(bits) - 1`
    - If true, we landed exactly on the last bit, meaning it's a standalone one-bit character
    - If false (we landed past the last index), the last `0` was consumed as part of a two-bit character

    &nbsp;

    This greedy approach works because the decoding is **deterministic** — there's only one valid way to decode any given sequence, and a `1` always forces a two-bit read.

  common_pitfalls:
    - title: Trying to Decode Backwards
      description: |
        It might seem intuitive to start from the end and work backwards, but this approach is tricky because characters are defined by their **first** bit, not their last.

        For example, in `[1, 0, 0]`, working backwards you'd see a `0` and wonder if it's standalone or the second half of `10`. The encoding is designed to be read forward, so decode forward.
      wrong_approach: "Iterating from the end of the array"
      correct_approach: "Iterate from the start, following the encoding rules"

    - title: Counting Ones Before the Last Zero
      description: |
        Some solutions try to count consecutive `1`s before the final `0` and check if the count is odd or even. While this can work, it's error-prone and less intuitive than simulating the actual decoding process.

        The simulation approach directly models the problem and is harder to get wrong.
      wrong_approach: "Counting 1s and using modular arithmetic"
      correct_approach: "Simulate the decoding by jumping 1 or 2 positions"

    - title: Off-by-One Errors
      description: |
        A common mistake is iterating until `i < len(bits)` instead of `i < len(bits) - 1`. This causes the loop to potentially decode the last element, which defeats the purpose of checking whether we land on it.

        We must stop **before** the last element to see if our decoding naturally lands on it.
      wrong_approach: "Loop while i < len(bits)"
      correct_approach: "Loop while i < len(bits) - 1"

  key_takeaways:
    - "**Greedy simulation**: When a sequence has deterministic decoding rules, simulate the process step by step"
    - "**Follow the encoding direction**: This encoding is designed to be read left-to-right; decode in the same direction"
    - "**Jump patterns**: Recognise when elements dictate variable-length jumps (1 consumes 2 positions, 0 consumes 1)"
    - "**Boundary condition**: The key insight is checking WHERE you land after decoding, not WHAT you decode"

  time_complexity: "O(n). We traverse the array once, visiting each element at most once."
  space_complexity: "O(1). We only use a single pointer variable `i`, regardless of input size."

solutions:
  - approach_name: Greedy Linear Scan
    is_optimal: true
    code: |
      def is_one_bit_character(bits: list[int]) -> bool:
          i = 0
          # Decode all characters except potentially the last one
          while i < len(bits) - 1:
              if bits[i] == 1:
                  # Two-bit character: skip the next bit too
                  i += 2
              else:
                  # One-bit character: move to next position
                  i += 1

          # If we land exactly on the last index, it's a one-bit character
          return i == len(bits) - 1
    explanation: |
      **Time Complexity:** O(n) — Single pass through the array.

      **Space Complexity:** O(1) — Only one integer variable used.

      We greedily decode the array from left to right. A `1` forces us to consume two bits, while a `0` consumes just one. After processing all characters before the last position, we check if we've landed exactly on the final index.

  - approach_name: Count Ones Before Last Zero
    is_optimal: false
    code: |
      def is_one_bit_character(bits: list[int]) -> bool:
          # Count consecutive 1s immediately before the last 0
          ones_count = 0
          # Start from second-to-last element, go backwards
          for i in range(len(bits) - 2, -1, -1):
              if bits[i] == 1:
                  ones_count += 1
              else:
                  break

          # If even number of 1s, they pair up, leaving last 0 alone
          # If odd number of 1s, the last 1 pairs with the final 0
          return ones_count % 2 == 0
    explanation: |
      **Time Complexity:** O(n) — Worst case, all elements before the last are `1`.

      **Space Complexity:** O(1) — Only a counter variable.

      This approach counts consecutive `1`s immediately preceding the final `0`. If the count is even, all `1`s pair up with each other (forming `11` characters), leaving the last `0` standalone. If odd, one `1` must pair with the final `0` (forming `10`), making the last character two-bit. While correct, this is less intuitive than simulating the decoding process.
