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 tilei
is red.colors[i] == 1
means that tilei
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:
-
Initialize Variables:
n
is the length of the originalcolors
array.ans
to keep track of the number of valid alternating groups.cnt
to count consecutive elements forming an alternating pattern.
-
Iterate Over the Double Length (2n):
- Use an index
i
which runs from0
to2n-1
. This effectively considers two rounds of the original circle, allowing handling of wraparound in a straightforward manner.
- Use an index
-
Count Alternating Tiles:
- For each
i
, check if the current and previous tiles (with wraparound using modulo operation) have different colors. If they differ, incrementcnt
. - If they have the same color (breaking the alternating pattern), reset
cnt
to1
.
- For each
-
Validate and Count Alternating Groups:
- Once
cnt
is at leastk
, andi
is greater than or equal ton
(indicating that a complete group from the original array context is formed), incrementans
.
- Once
-
Return Result:
- After traversing the unfolded conceptual array, return
ans
as the total number of alternating groups.
- After traversing the unfolded conceptual array, return
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 EvaluatorExample 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:
-
Initialize Variables:
n = 4
(length ofcolors
).ans = 0
to keep track of alternating groups.cnt = 1
to start counting potential alternating tiles.
-
Iterate Over the Double Length (8):
- We will simulate the circle by iterating over an array of length
2n = 8
.
- We will simulate the circle by iterating over an array of length
-
Count Alternating Tiles:
- For
i = 0
: Comparecolors[0 % 4]
(0
) andcolors[(0-1) % 4]
(1
), they differ, socnt = 2
. - For
i = 1
: Comparecolors[1 % 4]
(1
) andcolors[0 % 4]
(0
), they differ, socnt = 3
. - For
i = 2
: Comparecolors[2 % 4]
(0
) andcolors[1 % 4]
(1
), they differ, socnt = 4
. - For
i = 3
: Comparecolors[3 % 4]
(1
) andcolors[2 % 4]
(0
), they differ, socnt = 5
.
- For
-
Validate and Count Alternating Groups:
- For
i = 2
(andcnt = 4
), sincecnt >= k
andi >= n
, we identify a valid alternating group. Incrementans = 1
. - For
i = 3
(andcnt = 5
), sincecnt >= k
andi >= n
, incrementans = 2
.
- For
-
Return Result:
- Continue iteration for
i
values from 4 to 7, adjustingcnt
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.
- Continue iteration for
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.
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
https algomonster s3 us east 2 amazonaws com cover_photos stack svg Sliding Window Maximum Monotonic Stack We have an array and a sliding window defined by a start index and an end index The sliding window moves from left of the array to right There are always k elements in
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!