Alternating Groups II

medium array sliding window circular

Problem

A circle of tiles is given by an array colors, where 0 is red and 1 is blue. Because the tiles form a circle, the first and last tiles are neighbors. An alternating group is a block of k contiguous tiles whose colors strictly alternate — every tile inside the block (all but the two ends) differs from both its left and right neighbor. Count how many alternating groups exist.

Inputcolors = [0,1,0,1,0], k = 3
Output3
The length-3 windows starting at indices 0, 1 and 2 each alternate (0,1,0 / 1,0,1 / 0,1,0). The windows wrapping past the end fail, so the answer is 3.

def numberOfAlternatingGroups(colors, k):
    n = len(colors)
    ans = 0
    length = 1                       # current run of alternating tiles
    # walk i around the circle; n + k - 1 covers every wrapping window
    for i in range(1, n + k - 1):
        if colors[i % n] != colors[(i - 1) % n]:
            length += 1              # color flipped, extend the run
        else:
            length = 1               # equal neighbors break the run
        if length >= k:
            ans += 1                 # a length-k alternating window ends at i
    return ans
function numberOfAlternatingGroups(colors, k) {
  const n = colors.length;
  let ans = 0;
  let length = 1;                       // current run of alternating tiles
  // walk i around the circle; n + k - 1 covers every wrapping window
  for (let i = 1; i < n + k - 1; i++) {
    if (colors[i % n] !== colors[(i - 1) % n]) {
      length += 1;                      // color flipped, extend the run
    } else {
      length = 1;                       // equal neighbors break the run
    }
    if (length >= k) {
      ans += 1;                         // a length-k alternating window ends at i
    }
  }
  return ans;
}
int numberOfAlternatingGroups(int[] colors, int k) {
    int n = colors.length;
    int ans = 0;
    int length = 1;                      // current run of alternating tiles
    // walk i around the circle; n + k - 1 covers every wrapping window
    for (int i = 1; i < n + k - 1; i++) {
        if (colors[i % n] != colors[(i - 1) % n]) {
            length += 1;                 // color flipped, extend the run
        } else {
            length = 1;                  // equal neighbors break the run
        }
        if (length >= k) {
            ans += 1;                    // a length-k alternating window ends at i
        }
    }
    return ans;
}
int numberOfAlternatingGroups(vector<int>& colors, int k) {
    int n = colors.size();
    int ans = 0;
    int length = 1;                      // current run of alternating tiles
    // walk i around the circle; n + k - 1 covers every wrapping window
    for (int i = 1; i < n + k - 1; i++) {
        if (colors[i % n] != colors[(i - 1) % n]) {
            length += 1;                 // color flipped, extend the run
        } else {
            length = 1;                  // equal neighbors break the run
        }
        if (length >= k) {
            ans += 1;                    // a length-k alternating window ends at i
        }
    }
    return ans;
}
Time: O(n + k) Space: O(1)