As we need to compare the counts of tiring days and non-tiring days, we can use number 1 to indicate tiring day and -1 to indicate non-tiring day. Then, the sum of interval represented by -1/1 will reveal if tiring days are strictly greater than non-tiring days.
Then the goal of this problem becomes: find the longest interval such that the sum of this interval will be strictly greater than 0, and the length of this interval is the final answer.
First, let’s introduce some definitions:
- S(i,j)S_{(i, j)}S(i,j): the sum of interval
[i, j]
represented by -1/1 described above. The index of interval starts from 0. For example, if the interval is[1, -1, -1, 1]
, then S(1,3)=−1+(−1)+1=−1S_{(1, 3)} = -1 + (-1) + 1 = -1S(1,3)=−1+(−1)+1=−1. - SiS_iSi: abbreviation of S(0,i)S_{(0, i)}S(0,i).
Based on such notations, the final answer can be descibed as: for all position iii, find out the longest interval [h, i]
, such that 0≤h<i0 \le h \lt i0≤h<i and S(h,i)>0S_{(h, i)} \gt 0S(h,i)>0. And the answer of this problem is (i−h+1)(i - h + 1)(i−h+1) .
Apparently, this can be solved by pre-solved sub-problem with dynamic programming method.
For a specific position iii, define dp[i]
as the length of longest interval ending with iii and Si>0S_i \gt 0Si>0. Then the final answer should be the largest of dp[i]
, where 0≤i<input_arr_length0 \le i \lt input\_arr\_length0≤i<input_arr_length.
For a specifice position iii, if Si>0S_i \gt0Si>0, then dp[i]
equals (i+1)(i + 1)(i+1).
If Si≤0S_i \le 0Si≤0, dp[i]
is the length of longest interval [h, i]
, which satisfying conditions: 0≤h<i0\le h \lt i0≤h<i and S(h,i)>0S_{(h, i)} \gt 0S(h,i)>0.
As [0, i] = [0, h-1] + [h, i]
, we have Si=Sh−1+S(h,i)S_{i}=S_{h-1} + S_{(h, i)}Si=Sh−1+S(h,i), i.e. Si−Sh−1=S(h,i)>0S_{i} - S_{h-1} = S_{(h,i)} \gt 0Si−Sh−1=S(h,i)>0, which is equivalent to Si>Sh−1S_i \gt S_{h-1}Si>Sh−1. This tells us: if we can find interval satisfying above conditions, SiS_iSi must be strictly greater than Sh−1S_{h-1}Sh−1.
Suppose [k, i]
is the longest interval we’re searching for, we propose a statement that: S(k−1)=Si−1S_{(k-1)} = S_i - 1S(k−1)=Si−1, i.e. Sk−1S_{k-1}Sk−1 only less than 1 comparing to SiS_iSi, which can’t become a much smaller number.
Proof by contradiction: if Sk−1S_{k-1}Sk−1 can be smaller, as the change of each SiS_iSi is continuous with “1” difference, there must be a position jjj such that j<(k−1)j \lt (k-1)j<(k−1) and Sj=Si−1S_j = S_{i} - 1Sj=Si−1. Apparently, [j, i]
is a interval longer than [k, i]
, which contradicts the longest assumption that [k, j]
is the longest interval satisfying conditions.
Thus, if there exising longest interval [k, i]
, Sk−1S_{k-1}Sk−1 must be equal to Si−1S_i - 1Si−1. If there’s another pre-positions satisfying this equation, we should choose the smallest position to get the longest interval. So we only need to check if there’s a interval [0, k-1]
such that Sk−1S_{k-1}Sk−1 equals Si−1S_i - 1Si−1, and we choose the smallest position kkk as answer.
Specifically, we can use a map to store each pre-interval sum SiS_iSi as key, and its correpsonding position iii as value. We should add (key, val) pair of this map only when the key hasn’t been put into this map, which ensure it stores the smallest position of each sum value. Then, we only need to check if this map holds the key Si−1S_i -1Si−1. If it holds, we get a candidate answer (i−k+1)(i - k + 1)(i−k+1). Otherwise, it just shows there’s no interval such that the sum of [k, i]
is greater than 0.
private boolean isTiringDay(int work) {
return (work > 8);
}
public int longestWPI(int[] hours) {
if (null == hours) { return 0; }
int res = 0, sum = 0;
Map<Integer, Integer> sumMap = new HashMap<>();
for (int i = 0; i < hours.length; i++) {
sum += isTiringDay(hours[i]) ? 1 : -1;
if (sum > 0) {
res = i + 1;
} else {
sumMap.putIfAbsent(sum, i);
if (sumMap.containsKey(sum-1)) {
res = Math.max(res, i - sumMap.get(sum-1));
}
}
}
return res;
}