Facebook Pixel

2103. Rings and Rods

EasyHash TableString
Leetcode Link

Problem Description

You have n rings that can be red, green, or blue in color. These rings are placed on 10 different rods numbered from 0 to 9.

You're given a string rings with length 2n that tells you where each ring is placed. The string works in pairs - every two characters describe one ring:

  • The first character is the color: 'R' for red, 'G' for green, or 'B' for blue
  • The second character is the rod number: '0' through '9'

For example, if rings = "R3G2B1", this means:

  • A red ring is on rod 3
  • A green ring is on rod 2
  • A blue ring is on rod 1

Your task is to count how many rods have at least one ring of each color (red, green, AND blue).

The solution uses bit manipulation to track which colors are present on each rod. It assigns each color a bit value (R=1, G=2, B=4), and uses the OR operation to combine them. When a rod has all three colors, its value becomes 7 (which is 1+2+4 in binary: 111). The code then counts how many rods have the value 7.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that we need to track which colors appear on each rod, and we only care about whether a specific color is present or not (not how many times it appears).

Since there are only 3 colors and we need to track their presence/absence, this is a perfect use case for bit manipulation. We can think of each rod as having 3 binary flags - one for each color.

Why use bits? Consider that:

  • Red present/absent = 1 bit
  • Green present/absent = 1 bit
  • Blue present/absent = 1 bit

We can combine these into a single number where each bit position represents a different color. By assigning:

  • Red = 1 (binary: 001)
  • Green = 2 (binary: 010)
  • Blue = 4 (binary: 100)

When we use the OR operation (|), these values combine nicely:

  • If a rod has only red: value = 1 (binary: 001)
  • If a rod has red and green: value = 1 | 2 = 3 (binary: 011)
  • If a rod has all three colors: value = 1 | 2 | 4 = 7 (binary: 111)

The beauty of this approach is that 7 uniquely represents the state where all three colors are present. No other combination of colors can produce this value. So counting rods with all three colors simply becomes counting how many rods have the value 7.

This transforms a seemingly complex tracking problem into simple bit operations and a final count operation.

Solution Approach

We implement the solution using bit manipulation with the following steps:

  1. Initialize the tracking array: Create an array mask of size 10 (one for each rod from 0 to 9), initialized with zeros. Each element mask[i] will store the color information for rod i using bits.

  2. Define color mappings: Create a dictionary d that maps each color to its corresponding bit value:

    • "R" (Red) → 1 (binary: 001)
    • "G" (Green) → 2 (binary: 010)
    • "B" (Blue) → 4 (binary: 100)
  3. Process the rings string: Iterate through the string in steps of 2 (since each ring is described by 2 characters):

    for i in range(0, len(rings), 2):
        c = rings[i]        # Extract color character
        j = int(rings[i + 1])  # Extract rod number
        mask[j] |= d[c]     # Set the corresponding bit using OR operation

    The OR operation (|=) is crucial here - it sets the bit for the current color while preserving any previously set bits for other colors on the same rod.

  4. Count rods with all colors: After processing all rings, count how many elements in mask equal 7:

    return mask.count(7)

    Why 7? Because 7 in binary is 111, which means all three bits are set (red, green, and blue are all present).

Example walkthrough with rings = "R0G0B0R1G1":

  • Process "R0": mask[0] = 0 | 1 = 1 (rod 0 has red)
  • Process "G0": mask[0] = 1 | 2 = 3 (rod 0 has red and green)
  • Process "B0": mask[0] = 3 | 4 = 7 (rod 0 has all three colors)
  • Process "R1": mask[1] = 0 | 1 = 1 (rod 1 has red)
  • Process "G1": mask[1] = 1 | 2 = 3 (rod 1 has red and green)
  • Final count: Only mask[0] = 7, so return 1

The time complexity is O(n) where n is the length of the rings string, and space complexity is O(1) since we use a fixed-size array of 10 elements.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example with rings = "B5R5G4R4B4G5" to see how the bit manipulation solution works.

Initial Setup:

  • Create mask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (one slot for each rod 0-9)
  • Color mappings: R=1 (001), G=2 (010), B=4 (100)

Step-by-step Processing:

  1. Process "B5" (Blue ring on rod 5):

    • mask[5] |= 4
    • mask[5] = 0 | 4 = 4 (binary: 100)
    • Rod 5 now has: Blue
  2. Process "R5" (Red ring on rod 5):

    • mask[5] |= 1
    • mask[5] = 4 | 1 = 5 (binary: 101)
    • Rod 5 now has: Blue, Red
  3. Process "G4" (Green ring on rod 4):

    • mask[4] |= 2
    • mask[4] = 0 | 2 = 2 (binary: 010)
    • Rod 4 now has: Green
  4. Process "R4" (Red ring on rod 4):

    • mask[4] |= 1
    • mask[4] = 2 | 1 = 3 (binary: 011)
    • Rod 4 now has: Green, Red
  5. Process "B4" (Blue ring on rod 4):

    • mask[4] |= 4
    • mask[4] = 3 | 4 = 7 (binary: 111)
    • Rod 4 now has: Green, Red, Blue ✓
  6. Process "G5" (Green ring on rod 5):

    • mask[5] |= 2
    • mask[5] = 5 | 2 = 7 (binary: 111)
    • Rod 5 now has: Blue, Red, Green ✓

Final State:

  • mask = [0, 0, 0, 0, 7, 7, 0, 0, 0, 0]
  • Count elements equal to 7: mask[4] = 7 and mask[5] = 7
  • Answer: 2 (two rods have all three colors)

The key insight: The OR operation accumulates colors without losing information about previously placed rings, and the value 7 uniquely identifies rods with all three colors present.

Solution Implementation

1class Solution:
2    def countPoints(self, rings: str) -> int:
3        # Initialize a bitmask array for 10 rods (positions 0-9)
4        # Each element will store which colors are present on that rod
5        rod_color_mask = [0] * 10
6      
7        # Map each color to a unique bit position
8        # R=001 (bit 0), G=010 (bit 1), B=100 (bit 2)
9        color_to_bit = {"R": 1, "G": 2, "B": 4}
10      
11        # Process the string in pairs (color, rod_position)
12        for i in range(0, len(rings), 2):
13            color = rings[i]
14            rod_position = int(rings[i + 1])
15          
16            # Set the corresponding bit for this color on the rod
17            # Using bitwise OR to accumulate colors
18            rod_color_mask[rod_position] |= color_to_bit[color]
19      
20        # Count rods that have all three colors
21        # 7 in binary is 111, meaning all three bits are set (R, G, and B present)
22        return rod_color_mask.count(7)
23
1class Solution {
2    public int countPoints(String rings) {
3        // Create a mapping array to store color values
4        // Using ASCII values as indices for quick lookup
5        int[] colorValues = new int['Z'];
6        colorValues['R'] = 1;  // Red represented as bit 0 (001)
7        colorValues['G'] = 2;  // Green represented as bit 1 (010)
8        colorValues['B'] = 4;  // Blue represented as bit 2 (100)
9      
10        // Create a bitmask array for 10 rods (0-9)
11        // Each element will store which colors are present on that rod
12        int[] rodColorMask = new int[10];
13      
14        // Process the rings string in pairs (color, rod position)
15        for (int i = 0, length = rings.length(); i < length; i += 2) {
16            // Get the color character
17            int colorChar = rings.charAt(i);
18            // Get the rod position (convert from char to int)
19            int rodPosition = rings.charAt(i + 1) - '0';
20          
21            // Use bitwise OR to add the color to the rod's bitmask
22            rodColorMask[rodPosition] |= colorValues[colorChar];
23        }
24      
25        // Count rods that have all three colors
26        int count = 0;
27        for (int mask : rodColorMask) {
28            // Check if all three bits are set (R=1, G=2, B=4, sum=7)
29            if (mask == 7) {
30                count++;
31            }
32        }
33      
34        return count;
35    }
36}
37
1class Solution {
2public:
3    int countPoints(string rings) {
4        // Create a mapping array where 'R', 'G', 'B' map to bit values
5        // Using ASCII values as array indices
6        int colorToBit[90] = {0};  // 'Z' has ASCII value 90
7        colorToBit['R'] = 1;  // Red represented by bit 0
8        colorToBit['G'] = 2;  // Green represented by bit 1  
9        colorToBit['B'] = 4;  // Blue represented by bit 2
10      
11        // Array to store bitmask for each rod (0-9)
12        // Each rod's bitmask tracks which colors are present
13        int rodColorMask[10] = {0};
14      
15        // Process the input string in pairs (color, rod number)
16        for (int i = 0; i < rings.size(); i += 2) {
17            char color = rings[i];           // Get color character
18            int rodNumber = rings[i + 1] - '0';  // Convert char digit to int
19          
20            // Set the corresponding color bit for this rod using OR operation
21            rodColorMask[rodNumber] |= colorToBit[color];
22        }
23      
24        // Count rods that have all three colors (bitmask = 7 = 0b111)
25        // 7 means all three bits are set (Red, Green, and Blue all present)
26        return count(rodColorMask, rodColorMask + 10, 7);
27    }
28};
29
1/**
2 * Counts the number of rods that have all three colors (Red, Green, Blue) of rings
3 * @param rings - A string where each pair of characters represents a ring (color + rod position)
4 * @returns The number of rods containing all three colors
5 */
6function countPoints(rings: string): number {
7    // Helper function to convert a character to its alphabetical index
8    const getCharIndex = (char: string): number => {
9        return char.charCodeAt(0) - 'A'.charCodeAt(0);
10    };
11  
12    // Create a color-to-bitmask mapping array
13    // Using bit flags: R=1 (001), G=2 (010), B=4 (100)
14    const colorBitmask: number[] = Array(26).fill(0);
15    colorBitmask[getCharIndex('R')] = 1;  // Red represented as bit 0
16    colorBitmask[getCharIndex('G')] = 2;  // Green represented as bit 1
17    colorBitmask[getCharIndex('B')] = 4;  // Blue represented as bit 2
18  
19    // Array to track which colors are present on each rod (0-9)
20    // Each element uses bitwise OR to combine color flags
21    const rodColorMasks: number[] = Array(10).fill(0);
22  
23    // Process the rings string in pairs (color, rod position)
24    for (let i = 0; i < rings.length; i += 2) {
25        const color: string = rings[i];
26        const rodPosition: number = rings[i + 1].charCodeAt(0) - '0'.charCodeAt(0);
27      
28        // Use bitwise OR to add the color to the rod's bitmask
29        rodColorMasks[rodPosition] |= colorBitmask[getCharIndex(color)];
30    }
31  
32    // Count rods that have all three colors (bitmask = 7 = 111 in binary)
33    return rodColorMasks.filter(mask => mask === 7).length;
34}
35

Time and Space Complexity

The time complexity is O(n), where n is the length of the string rings. The algorithm iterates through the string once with a step of 2, processing each color-position pair in constant time. The loop runs n/2 iterations, and each iteration performs constant-time operations (dictionary lookup, integer conversion, and bitwise OR operation). The final count(7) operation on the mask array takes O(10) = O(1) time since the array has a fixed size of 10.

The space complexity is O(1) or more precisely O(|Σ|) where |Σ| represents the size of the character set. In this implementation, we use:

  • A fixed-size array mask of length 10 (for positions 0-9)
  • A dictionary d with 3 entries (for colors R, G, B)

Since both the number of possible positions (10) and the number of colors (3) are constants that don't depend on the input size, the space complexity is constant. The O(|Σ|) notation from the reference acknowledges that if the character set (number of colors or positions) were variable, the space would scale with it, but in this problem context, it remains O(1).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect String Parsing

A common mistake is incorrectly parsing the rings string, especially when dealing with the rod number character.

Pitfall Example:

# Wrong: Forgetting to convert rod character to integer
rod_position = rings[i + 1]  # This keeps it as a string '0'-'9'
rod_color_mask[rod_position] |= color_to_bit[color]  # TypeError!

Solution: Always convert the rod character to an integer:

rod_position = int(rings[i + 1])

2. Using Addition Instead of OR Operation

Some might try to add the bit values instead of using the OR operation, which leads to incorrect results when the same color appears multiple times on the same rod.

Pitfall Example:

# Wrong: Using addition
rod_color_mask[rod_position] += color_to_bit[color]
# If "R0R0" is in the string, rod 0 would have value 2 instead of 1

Solution: Use the bitwise OR operation to ensure each bit is set only once:

rod_color_mask[rod_position] |= color_to_bit[color]

3. Checking for Wrong Final Value

Understanding why we check for 7 specifically can be confusing. Some might check for other values or use incorrect logic.

Pitfall Example:

# Wrong: Checking if value is greater than 0
count = sum(1 for mask in rod_color_mask if mask > 0)

# Wrong: Checking for sum of all bits
count = sum(1 for mask in rod_color_mask if mask == 1 + 2 + 4)  # This works but shows misunderstanding

Solution: Remember that 7 represents all three bits being set (111 in binary). You can make this clearer by using a constant:

ALL_COLORS = 7  # Binary: 111 (R=1, G=2, B=4)
return rod_color_mask.count(ALL_COLORS)

4. Hardcoding Array Size Incorrectly

Since rods are numbered 0-9, the array must have exactly 10 elements.

Pitfall Example:

# Wrong: Creating array with 9 elements (forgetting 0-indexed counting)
rod_color_mask = [0] * 9  # This will cause IndexError for rod 9

Solution: Always initialize with 10 elements for rods 0 through 9:

rod_color_mask = [0] * 10
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following array represent a max heap?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More