Longest Well-Performing Interval
MEDIUMDescription
We are given hours, a list of the number of hours worked per day for a given employee.
A day is considered to be a tiring day if and only if the number of hours worked is (strictly) greater than 8.
A well-performing interval is an interval of days for which the number of tiring days is strictly larger than the number of non-tiring days.
Return the length of the longest well-performing interval.
Example 1:
Input: hours = [9,9,6,0,6,6,9] Output: 3 Explanation: The longest well-performing interval is [9,9,6].
Example 2:
Input: hours = [6,6,6] Output: 0
Constraints:
1 <= hours.length <= 1040 <= hours[i] <= 16
Approaches
Checkout 2 different approaches to solve Longest Well-Performing Interval. Click on different approaches to view the approach and algorithm in detail.
Prefix Sum with HashMap
A more efficient solution uses the concept of prefix sums combined with a HashMap. As before, we convert tiring days to +1 and non-tiring days to -1. We then compute the prefix sum as we iterate through this new score array.
The problem is to find indices i and j (i <= j) that maximize j - i + 1, such that the sum of scores from i to j is positive. This sum can be expressed as prefixSum[j] - prefixSum[i-1] > 0, or prefixSum[j] > prefixSum[i-1].
We can iterate through the array with index j, calculating the current_sum (which is prefixSum[j]). For each j, we need to find the earliest index i-1 where the prefix sum was smaller than current_sum. A HashMap is used to store the first index at which each prefix sum value appeared. This allows us to find the required i-1 efficiently.
Algorithm
- Transform the problem: represent tiring days as
+1and non-tiring days as-1. The goal is to find the longest subarray with a sum> 0. - This problem can be solved in a single pass using a HashMap and the concept of prefix sums.
- Initialize
sum = 0,maxLength = 0, and a HashMapmapto store the first-seen index of each prefix sum. Add a base casemap.put(0, -1)to handle intervals starting from index 0. - Iterate through the
hoursarray fromi = 0ton-1: a. Update the runningsum:sum += (hours[i] > 8) ? 1 : -1. b. Ifsumis not already in themap, store its first occurrence:map.put(sum, i). c. Check if the current prefix sumsumis positive. Ifsum > 0, it means the interval from the beginning[0, i]is well-performing. Its length isi + 1. UpdatemaxLength = max(maxLength, i + 1). d. Ifsum <= 0, we look for a previous prefix sumprev_sumsuch thatsum - prev_sum > 0, which simplifies toprev_sum < sum. To get the longest such interval ending ati, we need the earliest (smallest index)prev_sum. The best candidate for this issum - 1, as it represents the smallest possible positive difference (1). We check ifmap.containsKey(sum - 1). If it exists, it means we found an interval[map.get(sum - 1) + 1, i]with a sum of 1. We updatemaxLength = max(maxLength, i - map.get(sum - 1)). - Return
maxLength.
We iterate through the array once, maintaining a running sum. We use a HashMap to keep track of the first time we encounter each sum value. The key is the sum, and the value is the index.
We initialize the map with {0: -1} to correctly handle cases where a well-performing interval starts at index 0.
For each day i, we update our sum.
- If
sum > 0, the entire interval from the start[0, i]is well-performing. This has lengthi+1, which is the longest possible interval ending ati. We update our max length accordingly. - If
sum <= 0, a well-performing interval ending atimust start at somek > 0. We are looking for a previous prefix sum,prev_sum, that is less than the currentsum. To maximize the interval lengthi - k, we need the smallestk. The conditionsum - prev_sum > 0is equivalent toprev_sum <= sum - 1. The key insight is that we only need to check for the existence ofsum - 1in our map. Ifmap.containsKey(sum - 1), we have found an interval with a sum of at least 1, andmap.get(sum - 1)gives us the end index of the prefix that we subtract. The length of this interval isi - map.get(sum - 1). We update our max length with this value if it's larger.
We only add a sum to the map if it's not already there. This ensures we always have the earliest index for any given sum, which is crucial for finding the longest interval.
import java.util.HashMap;
import java.util.Map;
class Solution {
public int longestWPI(int[] hours) {
int maxLength = 0;
int sum = 0;
// Map to store the first occurrence of a prefix sum
Map<Integer, Integer> map = new HashMap<>();
// Base case for intervals starting at index 0
map.put(0, -1);
for (int i = 0; i < hours.length; i++) {
sum += (hours[i] > 8) ? 1 : -1;
// If the current sum is positive, the interval from the beginning is well-performing.
// This is the longest possible interval ending at i.
if (sum > 0) {
maxLength = i + 1;
} else {
// If sum <= 0, we look for a previous prefix sum `sum - 1`.
// This guarantees an interval sum of `sum - (sum - 1) = 1 > 0`.
// We check for `sum - 1` because it gives the longest possible interval
// for a subarray ending at `i` with a positive sum.
if (map.containsKey(sum - 1)) {
maxLength = Math.max(maxLength, i - map.get(sum - 1));
}
}
// Store the first time we see a particular sum.
// If the sum is already in the map, we don't update it because we want the earliest index.
map.putIfAbsent(sum, i);
}
return maxLength;
}
}
Complexity Analysis
Pros and Cons
- Highly efficient with linear time complexity.
- Solves the problem in a single pass through the input array.
- The logic can be less intuitive to derive compared to the brute-force approach.
- Requires extra space for the HashMap.
Code Solutions
Checking out 3 solutions in different languages for Longest Well-Performing Interval. Click on different languages to view the code.
class Solution { public int longestWPI ( int [] hours ) { int ans = 0 , s = 0 ; Map < Integer , Integer > pos = new HashMap <>(); for ( int i = 0 ; i < hours . length ; ++ i ) { s += hours [ i ] > 8 ? 1 : - 1 ; if ( s > 0 ) { ans = i + 1 ; } else if ( pos . containsKey ( s - 1 )) { ans = Math . max ( ans , i - pos . get ( s - 1 )); } pos . putIfAbsent ( s , i ); } return ans ; } }Video Solution
Watch the video walkthrough for Longest Well-Performing Interval
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.