Problem Statement
Brute Force [TLE]
class Solution:
def isArraySpecial(self, nums: List[int], queries: List[List[int]]) -> List[bool]:
res = []
for query in queries:
start, end = query
n = end - start + 1
temp = [0] * n
index = 0
for i in range(start, end + 1):
temp[index] = nums[i] % 2
index += 1
for i in range(n - 1):
if temp[i] == temp[i + 1]:
res.append(False)
break
else:
res.append(True)
return res
Another Approach [TLE]
class Solution:
def isArraySpecial(self, nums: List[int], queries: List[List[int]]) -> List[bool]:
res = []
prefix = []
for num in nums:
prefix.append(0 if num % 2 == 0 else 1)
arr = []
start = 0
end = 0
for end in range(1, len(prefix)):
if prefix[end] == prefix[end - 1]:
arr.append([start, end - 1])
start = end
arr.append([start, end])
for query in queries:
start, end = query
for interval in arr:
list_number = list(range(interval[0], interval[1] + 1))
if start in list_number and end in list_number:
res.append(True)
break
else:
res.append(False)
return res
Editorial Solution
Approach 1: Binary Search
class Solution:
def isArraySpecial(
self, nums: List[int], queries: List[Tuple[int, int]]
) -> List[bool]:
ans = [False] * len(queries)
violating_indices = []
for i in range(1, len(nums)):
# same parity, found violating index
if nums[i] % 2 == nums[i - 1] % 2:
violating_indices.append(i)
for i in range(len(queries)):
query = queries[i]
start = query[0]
end = query[1]
found_violating_index = self.binarySearch(
start + 1, end, violating_indices
)
if found_violating_index:
ans[i] = False
else:
ans[i] = True
return ans
def binarySearch(
self, start: int, end: int, violating_indices: List[int]
) -> bool:
left = 0
right = len(violating_indices) - 1
while left <= right:
mid = left + (right - left) // 2
violating_index = violating_indices[mid]
if violating_index < start:
# check right half
left = mid + 1
elif violating_index > end:
# check left half
right = mid - 1
else:
# violatingIndex falls in between start and end
return True
return False
Approach 2: Prefix Sum
class Solution:
def isArraySpecial(
self, nums: List[int], queries: List[List[int]]
) -> List[bool]:
ans = [False] * len(queries)
prefix = [0] * len(nums)
prefix[0] = 0
for i in range(1, len(nums)):
if nums[i] % 2 == nums[i - 1] % 2:
# new violative index found
prefix[i] = prefix[i - 1] + 1
else:
prefix[i] = prefix[i - 1]
for i in range(len(queries)):
query = queries[i]
start = query[0]
end = query[1]
ans[i] = prefix[end] - prefix[start] == 0
return ans
Approach 3: Sliding Window
class Solution:
def isArraySpecial(
self, nums: List[int], queries: List[List[int]]
) -> List[bool]:
n = len(nums)
max_reach = [0] * n
end = 0
# Step 1: Compute the maximum reachable index for each starting index
for start in range(n):
# Ensure 'end' always starts from the current index or beyond
end = max(end, start)
# Expand 'end' as long as adjacent elements have different parity
while end < n - 1 and nums[end] % 2 != nums[end + 1] % 2:
end += 1
# Store the farthest index reachable from 'start'
max_reach[start] = end
ans = []
# Step 2: Answer each query based on precomputed 'max_reach'
for start, end_query in queries:
# Check if the query range [start, end] lies within the max reachable range
ans.append(end_query <= max_reach[start])
return ans