Skip to content

Commit 9fe8e38

Browse files
committed
Alternating groups II
1 parent 557536a commit 9fe8e38

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

3208.alterating_group_ii/group.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# 3208. Alternating groups II
2+
# Topics: 'Sliding Window', 'Array'
3+
# Level: 'Medium'
4+
5+
# 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]:
6+
7+
# colors[i] == 0 means that tile i is red.
8+
# colors[i] == 1 means that tile i is blue.
9+
10+
# 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).
11+
12+
# Return the number of alternating groups.
13+
14+
# Note that since colors represents a circle, the first and the last tiles are considered to be next to each other.
15+
16+
17+
18+
# Example 1:
19+
20+
# Input: colors = [0,1,0,1,0], k = 3
21+
22+
# Output: 3
23+
24+
# Explanation:
25+
26+
# Alternating groups:
27+
28+
# Example 2:
29+
30+
# Input: colors = [0,1,0,0,1,0,1], k = 6
31+
32+
# Output: 2
33+
34+
# Explanation:
35+
36+
# Alternating groups:
37+
38+
# Example 3:
39+
40+
# Input: colors = [1,1,0,1], k = 4
41+
42+
# Output: 0
43+
44+
# Explanation:
45+
46+
47+
48+
# Constraints:
49+
50+
# 3 <= colors.length <= 105
51+
# 0 <= colors[i] <= 1
52+
# 3 <= k <= colors.length
53+
54+
from typing import List
55+
56+
class Solution:
57+
def numberOfAlternatingGroups(self, colors: List[int], k: int) -> int:
58+
for i in range(k-1):
59+
colors.append(colors[i])
60+
start = 0
61+
count = 0
62+
for i in range (len(colors)):
63+
if i != 0 and colors[i-1] == colors[i]:
64+
start = i
65+
elif i + 1 - start == k:
66+
start += 1
67+
count += 1
68+
return count
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
from typing import List
2+
import unittest
3+
4+
from group import Solution
5+
6+
class TestAlternatingGroups(unittest.TestCase):
7+
8+
def setUp(self):
9+
self.solution = Solution()
10+
11+
# Example test cases
12+
def test_example1(self):
13+
"""Test with colors = [0,1,0,1,0], k = 3"""
14+
colors = [0, 1, 0, 1, 0]
15+
k = 3
16+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 3)
17+
18+
def test_example2(self):
19+
"""Test with colors = [0,1,0,0,1,0,1], k = 6"""
20+
colors = [0, 1, 0, 0, 1, 0, 1]
21+
k = 6
22+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 2)
23+
24+
def test_example3(self):
25+
"""Test with colors = [1,1,0,1], k = 4"""
26+
colors = [1, 1, 0, 1]
27+
k = 4
28+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 0)
29+
30+
def test_all_ones(self):
31+
"""Test with all tiles blue"""
32+
colors = [1, 1, 1, 1]
33+
k = 3
34+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 0)
35+
36+
# Fully alternating patterns
37+
def test_fully_alternating_pattern(self):
38+
"""Test with perfect alternating pattern"""
39+
colors = [0, 1, 0, 1, 0, 1, 0, 1]
40+
k = 4
41+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 8)
42+
43+
def test_long_alternating_pattern(self):
44+
"""Test with longer alternating pattern"""
45+
colors = [0, 1] * 10 # [0,1,0,1,...] length 20
46+
k = 5
47+
self.assertEqual(self.solution.numberOfAlternatingGroups(colors, k), 20)
48+
49+
# Partial alternating patterns
50+
def test_one_break_in_pattern(self):
51+
"""Test with one break in alternating pattern"""
52+
colors = [0, 1, 0, 1, 1, 0, 1, 0]
53+
k = 4
54+
# Should find groups that don't include the break at index 4
55+
result = self.solution.numberOfAlternatingGroups(colors, k)
56+
self.assertGreaterEqual(result, 0)
57+
58+
def test_multiple_breaks(self):
59+
"""Test with multiple breaks in pattern"""
60+
colors = [0, 1, 1, 0, 1, 1, 0, 1]
61+
k = 3
62+
result = self.solution.numberOfAlternatingGroups(colors, k)
63+
self.assertGreaterEqual(result, 0)
64+
65+
def test_k_equals_3_mixed(self):
66+
"""Test with k=3 on mixed pattern"""
67+
colors = [1, 0, 1, 1, 0]
68+
k = 3
69+
result = self.solution.numberOfAlternatingGroups(colors, k)
70+
self.assertGreaterEqual(result, 0)
71+
72+
# Circular property tests
73+
def test_circular_connection_alternating(self):
74+
"""Test circular connection with alternating at boundaries"""
75+
colors = [1, 0, 1, 0]
76+
k = 3
77+
# Since it's circular: [1,0,1,0] connects to itself
78+
# Valid groups should consider wraparound
79+
result = self.solution.numberOfAlternatingGroups(colors, k)
80+
self.assertEqual(result, 4)
81+
82+
def test_circular_connection_non_alternating(self):
83+
"""Test circular connection with same color at boundaries"""
84+
colors = [0, 1, 0, 0]
85+
k = 3
86+
result = self.solution.numberOfAlternatingGroups(colors, k)
87+
self.assertGreaterEqual(result, 0)
88+
89+
# Larger arrays
90+
def test_large_array_mostly_alternating(self):
91+
"""Test with larger array that's mostly alternating"""
92+
colors = [0, 1] * 50 # Length 100
93+
k = 10
94+
result = self.solution.numberOfAlternatingGroups(colors, k)
95+
self.assertEqual(result, 100)
96+
97+
def test_large_array_with_breaks(self):
98+
"""Test with larger array with some breaks"""
99+
colors = [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1]
100+
k = 4
101+
result = self.solution.numberOfAlternatingGroups(colors, k)
102+
self.assertGreaterEqual(result, 0)
103+
104+
# Single valid group
105+
def test_exactly_one_group(self):
106+
"""Test where exactly one alternating group exists"""
107+
colors = [0, 0, 0, 1, 0, 1]
108+
k = 3
109+
result = self.solution.numberOfAlternatingGroups(colors, k)
110+
self.assertGreaterEqual(result, 0)
111+
112+
113+
if __name__ == '__main__':
114+
# Run tests with verbose output
115+
unittest.main(verbosity=2)

0 commit comments

Comments
 (0)