Facebook Pixel

3208. Alternating Groups II


Problem Description

There is a circle of red and blue tiles. You are given an array of integers colors and an integer k. The color of tile i is represented by colors[i]:

  • colors[i] == 0 means that tile i is red.
  • colors[i] == 1 means that tile i is blue.

An alternating group is every k contiguous tiles in the circle with alternating colors (each tile in the group except the first and last one has a different color from its left and right tiles).

Return the number of alternating groups.

Note that since colors represents a circle, the first and the last tiles are considered to be next to each other.

Intuition

The problem requires us to find the number of alternating groups of size k in a circular array of tiles represented by their colors. To solve this, we can unfold the circle into a straight line by imagining the array extended twice its length. This allows us to handle the circular nature of the problem without specifically dealing with wrap-around edges.

The approach involves iterating over this unfolded array, using a counter, cnt, to track the current length of a potential alternating group. We increase the counter when consecutive tiles have alternating colors and reset it when two consecutive tiles are the same color.

When the counter equals or exceeds k, and the index is at least one full circle length beyond the original array start, it indicates a valid alternating group. This condition accounts for only considering complete groups fitting within the original circular structure, ensuring accurate counting even as the circular array's beginning connects with its end.

Learn more about Sliding Window patterns.

Solution Approach

The main idea of the solution is to simulate a straight line from the circular array by iterating over a conceptual array that's double the length of colors array. This approach effectively handles the wraparound behavior of the circle by treating it as a linear traversal.

Here's a step-by-step breakdown of the algorithm:

  1. Initialize Variables:

    • n is the length of the original colors array.
    • ans to keep track of the number of valid alternating groups.
    • cnt to count consecutive elements forming an alternating pattern.
  2. Iterate Over the Double Length (2n):

    • Use an index i which runs from 0 to 2n-1. This effectively considers two rounds of the original circle, allowing handling of wraparound in a straightforward manner.
  3. Count Alternating Tiles:

    • For each i, check if the current and previous tiles (with wraparound using modulo operation) have different colors. If they differ, increment cnt.
    • If they have the same color (breaking the alternating pattern), reset cnt to 1.
  4. Validate and Count Alternating Groups:

    • Once cnt is at least k, and i is greater than or equal to n (indicating that a complete group from the original array context is formed), increment ans.
  5. Return Result:

    • After traversing the unfolded conceptual array, return ans as the total number of alternating groups.

The core of the solution leverages modular indexing to handle circular array behavior while utilizing a simple counting technique to track sequences and ensure alternating patterns. The use of a double-length array simulation is key to a clean and efficient solution.

Ready to land your dream job?

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

Start Evaluator

Example Walkthrough

Consider a scenario where the colors array is [0, 1, 0, 1] and k = 2. This example represents a circle of tiles with an alternating pattern of red (0) and blue (1).

Steps to Solve:

  1. Initialize Variables:

    • n = 4 (length of colors).
    • ans = 0 to keep track of alternating groups.
    • cnt = 1 to start counting potential alternating tiles.
  2. Iterate Over the Double Length (8):

    • We will simulate the circle by iterating over an array of length 2n = 8.
  3. Count Alternating Tiles:

    • For i = 0: Compare colors[0 % 4] (0) and colors[(0-1) % 4] (1), they differ, so cnt = 2.
    • For i = 1: Compare colors[1 % 4] (1) and colors[0 % 4] (0), they differ, so cnt = 3.
    • For i = 2: Compare colors[2 % 4] (0) and colors[1 % 4] (1), they differ, so cnt = 4.
    • For i = 3: Compare colors[3 % 4] (1) and colors[2 % 4] (0), they differ, so cnt = 5.
  4. Validate and Count Alternating Groups:

    • For i = 2 (and cnt = 4), since cnt >= k and i >= n, we identify a valid alternating group. Increment ans = 1.
    • For i = 3 (and cnt = 5), since cnt >= k and i >= n, increment ans = 2.
  5. Return Result:

    • Continue iteration for i values from 4 to 7, adjusting cnt as needed based on color patterns.
    • For this example, any subsequent evaluation past i = 3 does not introduce new valid groups within the original circle structure.

Ultimately, the function returns ans = 2 as the number of alternating groups of size k = 2 within the circle represented by colors = [0, 1, 0, 1].

Solution Implementation

1from typing import List
2
3class Solution:
4    def numberOfAlternatingGroups(self, colors: List[int], k: int) -> int:
5        n = len(colors)  # Get the length of the colors list
6        ans = 0  # Initialize the answer to 0, which will count valid alternating groups
7        cnt = 0  # Initialize the count of consecutive alternating colors
8
9        # Iterate over the list twice to account for circular nature
10        for i in range(n * 2):
11            # If the current color is the same as the previous, reset count
12            if i > 0 and colors[i % n] == colors[(i - 1) % n]:
13                cnt = 1
14            else:
15                # Increment the count for consecutive alternating colors
16                cnt += 1
17
18            # Check if in the second half of the iteration and count is at least k
19            # Increase the answer if conditions are met
20            if i >= n and cnt >= k:
21                ans += 1
22
23        return ans  # Return the total number of valid alternating groups
24
1class Solution {
2    public int numberOfAlternatingGroups(int[] colors, int k) {
3        int n = colors.length;  // Length of the colors array
4        int ans = 0;  // Counter for the number of valid alternating groups
5        int cnt = 0;  // Counter for the current group length
6
7        // Loop through twice the length of the array to handle circular groups
8        for (int i = 0; i < n << 1; ++i) {
9            // Check if the current color is the same as the previous one
10            if (i > 0 && colors[i % n] == colors[(i - 1) % n]) {
11                cnt = 1; // Reset group length if current color is the same as previous
12            } else {
13                ++cnt; // Increment group length as colors are alternating
14            }
15            // After the first full pass through the array, check if the group length is at least k
16            if (i >= n && cnt >= k) {
17                ans++; // If valid group of length k or more, increment answer
18            }
19        }
20        return ans; // Return the total number of valid groups
21    }
22}
23
1#include <vector>
2
3class Solution {
4public:
5    int numberOfAlternatingGroups(std::vector<int>& colors, int k) {
6        int n = colors.size();  // Get the size of the input vector
7        int ans = 0;            // Initialize a counter for alternating groups
8        int cnt = 0;            // Initialize a counter for the current group length
9
10        // Iterate through the array twice
11        for (int i = 0; i < n * 2; ++i) {
12            // Check if current color is the same as the previous one
13            if (i > 0 && colors[i % n] == colors[(i - 1) % n]) {
14                cnt = 1;  // Reset count if consecutive colors are the same
15            } else {
16                ++cnt;  // Increment current group length
17            }
18          
19            // If we've completed one loop and the group is at least of length k
20            if (i >= n && cnt >= k) {
21                ++ans;  // Increase the alternating groups count
22            }
23        }
24      
25        return ans;  // Return the total number of alternating groups
26    }
27};
28
1function numberOfAlternatingGroups(colors: number[], k: number): number {
2    const n = colors.length; // Get the length of the colors array
3    let ans = 0; // Initialize variable to store the count of alternating groups
4    let cnt = 0; // Initialize variable to keep track of the current group length
5
6    // Iterate twice over the colors array (n << 1 is equivalent to n * 2)
7    for (let i = 0; i < n * 2; ++i) {
8        // Check if the current color isn't alternating by comparing with the previous color
9        if (i && colors[i % n] === colors[(i - 1) % n]) {
10            cnt = 1; // Reset cnt to 1 if the current and previous colors are the same
11        } else {
12            ++cnt; // Increment cnt if the current and previous colors are different
13        }
14
15        // Check if there's a valid alternating group when the iteration index has passed n
16        // and the length of the group (cnt) is at least k
17        if (i >= n && cnt >= k) {
18            ans += 1; // Increment the count of alternating groups
19        }
20    }
21    return ans; // Return the total number of alternating groups found
22}
23

Time and Space Complexity

The time complexity of the code is O(n), where n is the length of the array colors. This is because the loop iterates 2 * n times, but each operation inside the loop takes constant time O(1). Since the complexity is dominated by the linear factor n, due to the modulo operations and comparisons, it is effectively O(n).

The space complexity is O(1), as the algorithm uses a fixed amount of additional space for variables ans and cnt, regardless of the input size n. No additional data structures are used that depend on the input size.

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


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

How would you design a stack which has a function min that returns the minimum element in the stack, in addition to push and pop? All push, pop, min should have running time O(1).


Recommended Readings

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


Load More