LeetCode: 1124

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&lt;i0 \le h \lt i0h<i and S(h,i)&gt;0S_{(h, i)} \gt 0S(h,i)>0. And the answer of this problem is (i−h+1)(i - h + 1)(ih+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&gt;0S_i \gt 0Si>0. Then the final answer should be the largest of dp[i], where 0≤i&lt;input_arr_length0 \le i \lt input\_arr\_length0i<input_arr_length.

For a specifice position iii, if Si&gt;0S_i \gt0Si>0, then dp[i] equals (i+1)(i + 1)(i+1).

If Si≤0S_i \le 0Si0, dp[i] is the length of longest interval [h, i], which satisfying conditions: 0≤h&lt;i0\le h \lt i0h<i and S(h,i)&gt;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=Sh1+S(h,i), i.e. Si−Sh−1=S(h,i)&gt;0S_{i} - S_{h-1} = S_{(h,i)} \gt 0SiSh1=S(h,i)>0, which is equivalent to Si&gt;Sh−1S_i \gt S_{h-1}Si>Sh1. This tells us: if we can find interval satisfying above conditions, SiS_iSi must be strictly greater than Sh−1S_{h-1}Sh1.

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(k1)=Si1, i.e. Sk−1S_{k-1}Sk1 only less than 1 comparing to SiS_iSi, which can’t become a much smaller number.

Proof by contradiction: if Sk−1S_{k-1}Sk1 can be smaller, as the change of each SiS_iSi is continuous with “1” difference, there must be a position jjj such that j&lt;(k−1)j \lt (k-1)j<(k1) and Sj=Si−1S_j = S_{i} - 1Sj=Si1. 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}Sk1 must be equal to Si−1S_i - 1Si1. 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}Sk1 equals Si−1S_i - 1Si1, 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 -1Si1. If it holds, we get a candidate answer (i−k+1)(i - k + 1)(ik+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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值