Facebook Pixel

3255. Find the Power of K-Size Subarrays II


Problem Description

You are given an array of integers nums of length n and a positive integer k.

The power of an array is defined as:

  • Its maximum element if all of its elements are consecutive and sorted in ascending order.
  • -1 otherwise.

You need to find the power of all subarrays of nums of size k.

Return an integer array results of size n - k + 1, where results[i] is the power of nums[i..(i + k - 1)].

Intuition

To solve this problem, consider the conditions that determine the power of each subarray: the subarray must be composed of consecutive and ascending integers. Our task is to efficiently verify these conditions for each possible subarray of length k.

Here's the approach in detail:

  1. Tracking Consecutive Subarrays: We use an array f to store the length of consecutive sequences ending at each position i in the nums array. Initially, set each f[i] to 1, as each element alone is a consecutive subarray of length 1.

  2. Identify Continuity: Traverse the array nums beginning from the second element. For each element at index i, check if it is one greater than the previous element (nums[i] == nums[i - 1] + 1). If true, update f[i] to f[i - 1] + 1, indicating that the consecutive sequence has extended by one more element.

  3. Evaluate Subarrays: After updating f, determine the power of each subarray of length k. For a subarray ending at index i (starting at i - k + 1), if f[i] is at least k, the subarray is a valid consecutive subsequence, and its power is its maximum element, nums[i]. Otherwise, the power is -1.

  4. Return the Results: Collect the power of each subarray in an array results and return it.

By systematically tracking the length of consecutive increasing sequences and checking these lengths against k, we can efficiently solve this problem using a single traversal of the array.

Learn more about Sliding Window patterns.

Solution Approach

The solution to the problem is implemented using an algorithm that leverages dynamic programming with the help of an auxiliary array f. Here's a step-by-step breakdown of the approach:

  1. Initialize the Auxiliary Array:

    • Create an array f of the same length as nums, where each element is initialized to 1. This array will keep track of the length of the current consecutive sequence ending at each position.
  2. Build the Consecutive Sequence Tracker:

    • Iterate through the nums array starting from the second element (index 1). For each element at index i, compare it with the previous element:
      • If nums[i] == nums[i - 1] + 1, it extends the existing consecutive sequence, so update f[i] to f[i - 1] + 1.
      • Otherwise, reset f[i] to 1, indicating the start of a new potential sequence.
  3. Calculate Subarray Power:

    • Iterate over the range from k - 1 to n (exclusive). For each index i, calculate the power of the subarray ending at i (which starts at i - k + 1 in nums):
      • If f[i] is greater than or equal to k, the subarray is a valid consecutive sequence, and its power is nums[i].
      • If f[i] is less than k, it means the subarray does not meet the required consecutive and ascending condition, and its power is -1.
  4. Return the Result:

    • Construct and return the results array containing the calculated power for each subarray of size k.

The solution efficiently processes the input array in a single pass to build the auxiliary f array, ensuring a time complexity of O(n), where n is the length of the input array nums.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through an example to illustrate the solution approach.

Consider the array nums = [1, 2, 4, 5, 6, 8] and k = 3. We want to find the power of all subarrays of size 3.

  1. Initialize the Auxiliary Array f:

    • Start with f = [1, 1, 1, 1, 1, 1]. Initially, each element is its own sequence.
  2. Build the Consecutive Sequence Tracker:

    • Compare nums[1] = 2 with nums[0] = 1. Since 2 is 1 + 1, update f[1] to 2. Now, f = [1, 2, 1, 1, 1, 1].
    • nums[2] = 4 and nums[1] = 2 are not consecutive, so f[2] stays 1.
    • nums[3] = 5 is 4 + 1, so update f[3] to f[2] + 1 = 2. Resulting in f = [1, 2, 1, 2, 1, 1].
    • nums[4] = 6 is 5 + 1, update f[4] to f[3] + 1 = 3. Now, f = [1, 2, 1, 2, 3, 1].
    • nums[5] = 8 and nums[4] = 6 are not consecutive, so f[5] remains 1.
  3. Calculate Subarray Power:

    • For subarray ending at index 2 (nums[0..2] = [1, 2, 4]), f[2] = 1, which is less than k, so power is -1.
    • For subarray ending at index 3 (nums[1..3] = [2, 4, 5]), f[3] = 2, which is less than k, so power is -1.
    • For subarray ending at index 4 (nums[2..4] = [4, 5, 6]), f[4] = 3, which is equal to k, so power is 6.
    • For subarray ending at index 5 (nums[3..5] = [5, 6, 8]), f[5] = 1, which is less than k, so power is -1.
  4. Return the Result:

    • Construct results = [-1, -1, 6, -1].

Thus, the power of each subarray of size 3 is [-1, -1, 6, -1].

Solution Implementation

1from typing import List
2
3class Solution:
4    def resultsArray(self, nums: List[int], k: int) -> List[int]:
5        # Get the length of the nums array
6        n = len(nums)
7      
8        # Initialize an array f to track continuous sequence lengths
9        f = [1] * n
10      
11        # Iterate through the nums array to calculate sequence lengths
12        for i in range(1, n):
13            # Check if the current number forms a consecutive sequence with the previous one
14            if nums[i] == nums[i - 1] + 1:
15                # Increment the sequence length based on the previous element
16                f[i] = f[i - 1] + 1
17      
18        # Create the results array. Use the value from nums if the sequence length is at least k, otherwise use -1
19        return [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)]
20
1import java.util.Arrays;
2
3class Solution {
4    public int[] resultsArray(int[] nums, int k) {
5        int n = nums.length;
6        int[] consecutiveLengths = new int[n];
7        Arrays.fill(consecutiveLengths, 1); // Initialize all elements to 1 since each element alone is a sequence of length 1
8      
9        // Compute the lengths of increasing consecutive subarrays
10        for (int i = 1; i < n; ++i) {
11            if (nums[i] == nums[i - 1] + 1) {
12                consecutiveLengths[i] = consecutiveLengths[i - 1] + 1;
13            }
14        }
15      
16        int[] result = new int[n - k + 1];
17      
18        // Determine if the length of the increasing sequence ending at each element is at least k
19        for (int i = k - 1; i < n; ++i) {
20            if (consecutiveLengths[i] >= k) {
21                result[i - k + 1] = nums[i]; // If so, store the ending element of that sequence
22            } else {
23                result[i - k + 1] = -1; // Otherwise, mark it as -1
24            }
25        }
26      
27        return result;
28    }
29}
30
1#include <vector>
2
3class Solution {
4public:
5    // Function to process the input array and return a modified results array
6    std::vector<int> resultsArray(std::vector<int>& nums, int k) {
7        int n = nums.size(); // Get the size of the input array
8        std::vector<int> f(n); // Initialize a vector to store length of increasing subsequences
9        f[0] = 1; // The first element always starts a new subsequence of at least length 1
10
11        // Iterate through the array to populate f with lengths of increasing subsequences
12        for (int i = 1; i < n; ++i) {
13            // Check if the current number is a continuation of an increasing sequence
14            if (nums[i] == nums[i - 1] + 1) {
15                f[i] = f[i - 1] + 1; // Extend the previous sequence by 1
16            } else {
17                f[i] = 1; // Start a new sequence
18            }
19        }
20
21        std::vector<int> ans; // Vector to store the final results
22
23        // Go through the array to build the results vector based on the length of increasing subsequences
24        for (int i = k - 1; i < n; ++i) {
25            // If the sequence ending at index i is at least length k, take the element; otherwise, take -1
26            if (f[i] >= k) {
27                ans.push_back(nums[i]); // Use the element at the current index
28            } else {
29                ans.push_back(-1); // Otherwise, use -1
30            }
31        }
32
33        return ans; // Return the results vector
34    }
35};
36
1/**
2 * This function takes an array of numbers and an integer k, and returns a new array
3 * based on a specific condition related to consecutive increasing sequences.
4 *
5 * @param nums - The array of numbers to process.
6 * @param k - The length threshold for consecutive increasing sequences.
7 * @returns An array of numbers where each element represents the last number in a
8 * consecutive increasing sequence of at least length k, or -1 if no such sequence exists.
9 */
10function resultsArray(nums: number[], k: number): number[] {
11    const n: number = nums.length; // Get the length of the input array
12    const f: number[] = Array(n).fill(1); // Initialize an array to store the length of increasing sequences, default to 1
13
14    // Iterate over the array starting from the second element
15    for (let i: number = 1; i < n; ++i) {
16        // Check if the current element is consecutive from the previous element
17        if (nums[i] === nums[i - 1] + 1) {
18            f[i] = f[i - 1] + 1; // Increase the sequence length by 1
19        }
20    }
21
22    const ans: number[] = []; // Initialize an array to store the results
23
24    // Iterate over the array starting from the (k-1)-th element
25    for (let i: number = k - 1; i < n; ++i) {
26        // Check if the length of the sequence is at least k
27        if (f[i] >= k) {
28            ans.push(nums[i]); // If true, add the current number to results
29        } else {
30            ans.push(-1); // Otherwise, add -1
31        }
32    }
33
34    return ans; // Return the results array
35}
36

Time and Space Complexity

The code processes the input list nums which has a length of n. The time complexity is determined by the way the list is traversed and modified.

  • The loop for i in range(1, n): iterates over the list nums once, performing a constant-time check and possibly updating the list f. Thus, this loop contributes a time complexity of O(n).

  • The list comprehension [nums[i] if f[i] >= k else -1 for i in range(k - 1, n)] also iterates through part of nums once, leading to another O(n) operation depending on the values of k and n.

Combining these, the overall time complexity of the code is O(n).

The space complexity is determined by the extra space used:

  • The list f is initialized with one element for each element in nums, contributing a space complexity of O(n).

  • The output list generated by the list comprehension also holds up to n elements, but it's essentially the answer being output, thus not adding to auxiliary space complexity.

Therefore, the total space complexity remains O(n), as any additional space used is directly proportional to n.

Learn more about how to find time and space complexity quickly.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

Which algorithm should you use to find a node that is close to the root of the tree?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More