LeetCode 3254 - Find the Power of K-Size Subarrays I
The problem asks us to examine every contiguous subarray of length k in the input array nums and determine its "power". A subarray has valid power only if two conditions are simultaneously true: 1. The elements are sorted in strictly ascending order. 2.
Difficulty: 🟡 Medium
Topics: Array, Sliding Window
Solution
Problem Understanding
The problem asks us to examine every contiguous subarray of length k in the input array nums and determine its "power".
A subarray has valid power only if two conditions are simultaneously true:
- The elements are sorted in strictly ascending order.
- Every adjacent pair differs by exactly
1, meaning the sequence is consecutive.
If both conditions hold, the power is simply the maximum element of that subarray. Since the sequence is strictly ascending and consecutive, the maximum element is always the last element.
Otherwise, the power is -1.
For example, consider the subarray [2, 3, 4]:
- It is sorted in ascending order.
- Every pair differs by
1.
So its power is 4.
Now consider [3, 4, 3]:
- It is not sorted in ascending order.
- The consecutive property also fails.
So its power is -1.
The input consists of:
nums, an integer array of lengthnk, the required subarray size
We must return an array of size n - k + 1, where each position contains the power of the corresponding window.
The constraints are relatively small:
n <= 500
This means even an O(n * k) solution is completely acceptable because the worst case is only 500 * 500 = 250000 operations.
Still, there is a cleaner sliding window style solution that processes the array more efficiently in linear time.
Several edge cases are important:
k = 1, every single element subarray is automatically consecutive and sorted, so the answer is simply the original array.- Arrays with duplicate values, such as
[2,2,2], fail because consecutive ascending numbers require differences of exactly1. - Descending arrays fail because the order requirement is violated.
- A sequence can be ascending but not consecutive, such as
[1,3,5]. - A sequence can contain one invalid adjacent pair that invalidates the entire window.
Approaches
Brute Force
The most direct solution is to examine every subarray of size k.
For each window:
- Check every adjacent pair.
- Verify that:
nums[i + 1] == nums[i] + 1
- If all adjacent pairs satisfy the condition, return the last element of the window.
- Otherwise, return
-1.
This works because a strictly ascending consecutive sequence is fully characterized by adjacent differences of exactly 1.
The brute force method is straightforward and easy to reason about. However, for every window we repeatedly recheck many adjacent pairs that overlap with previous windows.
Since there are n - k + 1 windows and each requires up to k - 1 comparisons, the complexity is O(n * k).
Optimal Sliding Window Observation
The key observation is that validity depends only on adjacent pairs.
Define a pair as "good" if:
nums[i + 1] == nums[i] + 1
For a window of size k to be valid, all k - 1 adjacent pairs inside that window must be good.
Instead of rechecking the entire window each time, we can maintain the length of the current consecutive ascending streak.
If:
nums[i] == nums[i - 1] + 1
then we extend the streak.
Otherwise, we reset it.
Whenever the streak length becomes at least k, the current window ending at index i is valid, and its power is nums[i].
This transforms the solution into a linear scan.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * k) | O(1) | Checks every window independently |
| Optimal | O(n) | O(1) | Tracks consecutive ascending streak length |
Algorithm Walkthrough
- Initialize the result array with size
n - k + 1, filled with-1.
We default every window to invalid. Only valid windows will be updated later.
2. Maintain a variable called streak.
streak represents the length of the current consecutive ascending sequence ending at the current index.
3. Start with streak = 1.
A single element always forms a valid streak of length 1.
4. Iterate through the array from left to right.
For each index i starting from 1:
- If
nums[i] == nums[i - 1] + 1, extend the streak:
streak += 1
- Otherwise, reset:
streak = 1
- Determine whether a valid window of size
kends at indexi.
If:
streak >= k
then the subarray:
nums[i-k+1 : i+1]
is consecutive and ascending. 6. Store the power.
Since the window is ascending, the maximum value is the last element:
nums[i]
So:
result[i-k+1] = nums[i]
- Handle the special case
k == 1.
Every individual element is valid, so the answer is simply nums.
Why it works
The algorithm maintains the invariant that streak equals the length of the longest suffix ending at the current index that forms a consecutive ascending sequence.
A window of size k is valid exactly when this suffix length is at least k. Because every adjacent pair inside the window differs by 1, the window must be strictly ascending and consecutive.
Thus every valid window is detected exactly once, and every invalid window remains -1.
Python Solution
from typing import List
class Solution:
def resultsArray(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
if k == 1:
return nums[:]
result = [-1] * (n - k + 1)
streak = 1
for i in range(1, n):
if nums[i] == nums[i - 1] + 1:
streak += 1
else:
streak = 1
if streak >= k:
result[i - k + 1] = nums[i]
return result
The implementation begins by handling the special case where k == 1. Any single element subarray is trivially consecutive and ascending, so we return a copy of the original array.
Next, we create the result array initialized with -1. This automatically marks all windows invalid unless proven otherwise.
The streak variable tracks how many consecutive ascending elements currently extend to index i.
During iteration:
- If the current element continues the consecutive pattern, we increase
streak. - Otherwise, we reset it to
1.
Whenever streak >= k, we know the current window of size k ending at index i is valid. Since the sequence is ascending, the maximum element is the final element, nums[i].
The algorithm performs a single pass through the array and uses only constant extra memory.
Go Solution
func resultsArray(nums []int, k int) []int {
n := len(nums)
if k == 1 {
result := make([]int, n)
copy(result, nums)
return result
}
result := make([]int, n-k+1)
for i := range result {
result[i] = -1
}
streak := 1
for i := 1; i < n; i++ {
if nums[i] == nums[i-1]+1 {
streak++
} else {
streak = 1
}
if streak >= k {
result[i-k+1] = nums[i]
}
}
return result
}
The Go implementation follows the same logic as the Python solution.
One small difference is that Go slices are initialized with zero values, so we explicitly fill the result slice with -1.
For the k == 1 case, we create a copy of the input slice before returning it. This avoids returning the original underlying slice directly.
No integer overflow concerns exist because values remain well within Go's standard integer range.
Worked Examples
Example 1
Input:
nums = [1,2,3,4,3,2,5]
k = 3
We track the streak length while scanning.
| i | nums[i] | Relation | streak | Valid Window? | result |
|---|---|---|---|---|---|
| 1 | 2 | 2 = 1 + 1 | 2 | No | [-1,-1,-1,-1,-1] |
| 2 | 3 | 3 = 2 + 1 | 3 | Yes | [3,-1,-1,-1,-1] |
| 3 | 4 | 4 = 3 + 1 | 4 | Yes | [3,4,-1,-1,-1] |
| 4 | 3 | Breaks | 1 | No | [3,4,-1,-1,-1] |
| 5 | 2 | Breaks | 1 | No | [3,4,-1,-1,-1] |
| 6 | 5 | Breaks | 1 | No | [3,4,-1,-1,-1] |
Final answer:
[3,4,-1,-1,-1]
Example 2
Input:
nums = [2,2,2,2,2]
k = 4
| i | nums[i] | Relation | streak | Valid Window? |
|---|---|---|---|---|
| 1 | 2 | Not consecutive | 1 | No |
| 2 | 2 | Not consecutive | 1 | No |
| 3 | 2 | Not consecutive | 1 | No |
| 4 | 2 | Not consecutive | 1 | No |
No valid window ever appears.
Final answer:
[-1,-1]
Example 3
Input:
nums = [3,2,3,2,3,2]
k = 2
| i | nums[i] | Relation | streak | result |
|---|---|---|---|---|
| 1 | 2 | Breaks | 1 | [-1,-1,-1,-1,-1] |
| 2 | 3 | 3 = 2 + 1 | 2 | [-1,3,-1,-1,-1] |
| 3 | 2 | Breaks | 1 | [-1,3,-1,-1,-1] |
| 4 | 3 | 3 = 2 + 1 | 2 | [-1,3,-1,3,-1] |
| 5 | 2 | Breaks | 1 | [-1,3,-1,3,-1] |
Final answer:
[-1,3,-1,3,-1]
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Single pass through the array |
| Space | O(1) | Only a few extra variables besides output |
The algorithm scans the array exactly once. Every iteration performs only constant time operations, so the total runtime is linear in the size of the input.
The extra memory usage is constant because we only store the streak variable and loop counters. The output array does not count toward auxiliary space complexity.
Test Cases
from typing import List
class Solution:
def resultsArray(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
if k == 1:
return nums[:]
result = [-1] * (n - k + 1)
streak = 1
for i in range(1, n):
if nums[i] == nums[i - 1] + 1:
streak += 1
else:
streak = 1
if streak >= k:
result[i - k + 1] = nums[i]
return result
sol = Solution()
assert sol.resultsArray([1,2,3,4,3,2,5], 3) == [3,4,-1,-1,-1] # provided example
assert sol.resultsArray([2,2,2,2,2], 4) == [-1,-1] # duplicates break consecutiveness
assert sol.resultsArray([3,2,3,2,3,2], 2) == [-1,3,-1,3,-1] # alternating valid pairs
assert sol.resultsArray([5], 1) == [5] # single element array
assert sol.resultsArray([1,2,3,4], 1) == [1,2,3,4] # k = 1 always valid
assert sol.resultsArray([1,2,3,4], 4) == [4] # entire array valid
assert sol.resultsArray([4,3,2,1], 2) == [-1,-1,-1] # descending order invalid
assert sol.resultsArray([1,3,5,7], 2) == [-1,-1,-1] # ascending but not consecutive
assert sol.resultsArray([1,2,4,5,6], 3) == [-1,6,-1] # only middle window valid
assert sol.resultsArray([10,11,12,13,14], 2) == [11,12,13,14] # every window valid
assert sol.resultsArray([1,2,3,5,6,7], 3) == [3,-1,-1,7] # two separate valid segments
Test Summary
| Test | Why |
|---|---|
[1,2,3,4,3,2,5], k=3 |
Standard mixed validity example |
[2,2,2,2,2], k=4 |
Duplicate values invalidate windows |
[3,2,3,2,3,2], k=2 |
Alternating valid and invalid windows |
[5], k=1 |
Smallest possible input |
[1,2,3,4], k=1 |
Every single element window is valid |
[1,2,3,4], k=4 |
Entire array forms one valid window |
[4,3,2,1], k=2 |
Descending sequences fail |
[1,3,5,7], k=2 |
Ascending but non-consecutive values |
[1,2,4,5,6], k=3 |
Partial validity inside array |
[10,11,12,13,14], k=2 |
Every window valid |
[1,2,3,5,6,7], k=3 |
Multiple separate valid streaks |
Edge Cases
One important edge case occurs when k = 1. A single element is always trivially sorted and consecutive because there are no adjacent pairs to violate the conditions. A buggy implementation might incorrectly return -1 or fail to initialize the result properly. The solution handles this immediately by returning a copy of nums.
Another important case involves duplicate values such as [2,2,2]. Even though the values appear ordered, they are not strictly ascending and consecutive because the difference between adjacent values is 0 instead of 1. The implementation correctly rejects these windows because it explicitly checks for nums[i] == nums[i - 1] + 1.
Descending sequences such as [5,4,3] are another common source of mistakes. A naive implementation that only checks whether values differ by 1 without considering direction could accidentally accept them. The algorithm avoids this issue because it specifically requires the next value to equal the previous value plus one.
Another subtle case is ascending but non-consecutive sequences like [1,3,5]. These arrays are increasing, but gaps larger than 1 invalidate the window. Since the implementation checks exact equality with previous + 1, these windows are correctly marked invalid.