Skip to main content

Alternating Groups III - Solution & Explanation

Practice this problem

Problem Statement

There are some red and blue tiles arranged circularly. You are given an array of integers colors and a 2D integers array queries.

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 a contiguous subset of tiles in the circle with alternating colors (each tile in the group except the first and last one has a different color from its adjacent tiles in the group).

You have to process queries of two types:

  • queries[i] = [1, sizei], determine the count of alternating groups with size sizei.
  • queries[i] = [2, indexi, colori], change colors[indexi] to colori.

Return an array answer containing the results of the queries of the first type in order.

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

 

Example 1:

Input: colors = [0,1,1,0,1], queries = [[2,1,0],[1,4]]

Output: [2]

Explanation:

First query:

Change colors[1] to 0.

Second query:

Count of the alternating groups with size 4:

Example 2:

Input: colors = [0,0,1,0,1,1], queries = [[1,3],[2,3,0],[1,5]]

Output: [2,0]

Explanation:

First query:

Count of the alternating groups with size 3:

Second query: colors will not change.

Third query: There is no alternating group with size 5.

 

Constraints:

  • 4 <= colors.length <= 5 * 104
  • 0 <= colors[i] <= 1
  • 1 <= queries.length <= 5 * 104
  • queries[i][0] == 1 or queries[i][0] == 2
  • For all i that:
    • queries[i][0] == 1: queries[i].length == 2, 3 <= queries[i][1] <= colors.length - 1
    • queries[i][0] == 2: queries[i].length == 3, 0 <= queries[i][1] <= colors.length - 1, 0 <= queries[i][2] <= 1

Approach Overview

Problem Overview: You are given a circular array of colors and a sequence of queries. Some queries update the color at an index, while others ask how many alternating groups of a given size exist in the array. An alternating group means adjacent elements strictly alternate (e.g., 0,1,0,1). Because updates modify the structure dynamically, the solution must efficiently maintain alternating segments while answering queries quickly.

Approach 1: Recursive Approach with Memoization (Brute-Force Simulation) (Time: O(n * q), Space: O(n))

The most direct method recomputes alternating segments whenever a query asks for the number of valid groups. Traverse the array and recursively check whether consecutive elements alternate, storing intermediate results with memoization to avoid recomputing overlapping segments. For each query, scan the array and count segments whose length satisfies the requested size. This works for small inputs but becomes slow when updates and queries are frequent because each query may require scanning most of the array.

Approach 2: Dynamic Programming with Binary Indexed Tree (Optimal) (Time: O((n + q) log n), Space: O(n))

The efficient strategy tracks maximal alternating segments instead of recomputing them from scratch. First, determine whether each adjacent pair alternates. This transforms the problem into maintaining runs of valid alternating edges. When a color update occurs, only the two neighboring relationships change, so the affected segments can be split or merged locally. Use a Binary Indexed Tree to store counts of segment lengths and support prefix queries for "how many segments have length ≥ k".

Dynamic programming ideas help maintain the length of alternating runs starting at each index. When an update breaks or forms alternation, adjust the boundaries of the affected segments and update their lengths in the Fenwick tree. Each modification touches only a constant number of segments, keeping updates efficient. Query operations then become simple range queries over segment lengths using the BIT.

This approach works well because it converts a structural property of the array into a frequency problem that a Fenwick tree handles efficiently. The array itself is still accessed directly for updates, while the BIT maintains aggregate statistics about segment sizes.

Recommended for interviews: The Binary Indexed Tree solution is what interviewers expect for a hard problem with dynamic updates. The brute-force or recursive simulation demonstrates you understand how alternating groups are formed, but the optimized structure shows you can maintain derived properties under updates. Strong candidates recognize that only local relationships change after an update and use data structures like a array plus Fenwick tree or segment tree to maintain counts efficiently. Concepts from dynamic programming help track alternating run lengths, while the BIT enables fast aggregated queries.

Approach 1: Dynamic Programming Approach

This approach leverages dynamic programming to solve the problem by breaking it down into subproblems and storing their solutions for reuse. It is beneficial in cases where the problem exhibits overlapping subproblems and optimal substructure properties. By using a table to keep track of solutions to subproblems, this approach reduces the time complexity significantly compared to naive methods.

This solution demonstrates the use of dynamic programming in C. We initialize an array dp to store the results of subproblems. Starting from the base cases, we iteratively fill the array until we reach the desired solution. This avoids redundant calculations.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n).
Space Complexity: O(n). Both are linear due to the storage used for the dp array.

Try this approach in the editor →

Approach 2: Recursive Approach with Memoization

This approach uses a recursive function to solve the problem, complemented by memoization to store previously calculated results. By caching the results of function calls, this method combines the simplicity of recursive solutions with the efficiency of iterative dynamic programming, thus reducing redundant computations drastically.

The C code uses an array dp initialized with -1 as a memoization technique to store values of previous computations. This avoids unnecessary recursive calls.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n).
Space Complexity: O(n) due to the recursive stack and memoization array.

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Dynamic Programming Approach

Time Complexity: O(n).
Space Complexity: O(n). Both are linear due to the storage used for the dp array.

Recursive Approach with Memoization

Time Complexity: O(n).
Space Complexity: O(n) due to the recursive stack and memoization array.

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Recursive Simulation with MemoizationO(n * q)O(n)Good for understanding how alternating groups form; feasible only when constraints are small
Dynamic Programming + Binary Indexed TreeO((n + q) log n)O(n)Best for large inputs with frequent updates and queries; maintains segment counts efficiently

Video Solution

3245. Alternating Groups III | Weekly Leetcode 409 • codingMohan • 1,861 views views

Watch 2 more video solutions →

Frequently Asked Questions

Is Alternating Groups III easy or hard?
Alternating Groups III is classified as Hard with a low acceptance rate around 19%. The difficulty comes from handling dynamic updates while maintaining alternating segment information efficiently using advanced data structures like Fenwick trees.
What is the best approach for Alternating Groups III?
The most efficient approach maintains alternating segments dynamically using a Binary Indexed Tree (Fenwick tree). Instead of recomputing groups after every update, track segment lengths and update only the affected boundaries when a color changes. Each update and query runs in O(log n) time.
Is Alternating Groups III asked at Google/Amazon/Meta?
Problems involving dynamic arrays, Fenwick trees, and segment maintenance appear frequently in interviews at companies like Google, Amazon, and Meta. Alternating Groups III reflects the same pattern: maintain structural properties under updates and answer queries efficiently.
What data structure is used in Alternating Groups III?
The key data structure is a Binary Indexed Tree (Fenwick tree), used to maintain counts of alternating segment lengths and support fast prefix queries. The underlying array stores colors, while the tree tracks aggregated statistics for efficient queries.
What is the time complexity of Alternating Groups III?
The optimized solution using a Binary Indexed Tree runs in O((n + q) log n) time, where n is the number of elements and q is the number of queries. Each update modifies only nearby relationships and updates the Fenwick tree in O(log n). Space complexity is O(n).
Alternating Groups III Python or Java solution approach?
In Python or Java, implement a Fenwick tree class that supports update and prefix-sum operations. Maintain alternating segment boundaries in arrays or sets, update them when a color changes, and update the Fenwick tree with the new segment lengths. Each operation runs in O(log n).
How to solve Alternating Groups III in O(log n) per query?
Track maximal alternating segments and store their lengths in a Fenwick tree. When a color update occurs, only the two adjacent relationships may change, which can split or merge segments. Update those segment lengths in the tree, and answer queries by counting segments whose length satisfies the required size using prefix sums.

Ready to solve this problem?

Practice Alternating Groups III with our built-in code editor and test cases.

Practice on FleetCode