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: - slug: greedy is_optimal: true function_signature: "def is_one_bit_character(bits: list[int]) -> bool:" test_cases: visible: - input: { bits: [1, 0, 0] } expected: true - input: { bits: [1, 1, 1, 0] } expected: false hidden: - input: { bits: [0] } expected: true - input: { bits: [0, 0] } expected: true - input: { bits: [1, 0] } expected: false - input: { bits: [1, 1, 0] } expected: true - input: { bits: [0, 1, 0] } expected: false 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   **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`)   **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   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.