Fork me on GitHub

【数据结构】算法 Longest Well-Performing Interval 表现良好的最长时间段

Longest Well-Performing Interval 表现良好的最长时间段

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.

每天的work time >8,代表这一天 tiring,表现良好的时间段,注意是时间段,被标记为tiring的天数要大于非tiring的天数,并且把这个时间段长度返回。

Input: hours = [9,9,6,0,6,6,9]
Output: 3
Explanation: The longest well-performing interval is [9,9,6].

思路

将问题进行转换:

数组元素a[i]>8,就标记b[i]=1,否则b[i]=-1。

原来的a数组[9,9,6,0,6,6,9],会得到新数组b[1,1,-1,-1,-1,-1,1].此时我们是要寻找到b数组中区间和大于0 的部分。

继续转换,将b数组的元素,转换为前缀和。c数组 ,c[i]=c[i-1]+c[i-2].....+c[0].由此可知c数组为[1,2,1,0,-1,-2,-1],此时问题转换为寻找c数组中c[j]-c[i]>0,(j>i)时,并且是长度最长的一段。

如何能保证当j>i时 c[j]-c[i]>0。用人类的语言来说,就是从j位置向前寻找一个比c[j]小的数,这样才能保证 c[j]-c[i]>0。

而且c数组是一组连续的数字,所以在从j位置向前寻找比c[j]小的数,如果存在的话,那么c[i]一定是满足c[j]-1= c[i];否则j前面就不会存在比c[j]小的数,从而就无法保证 c[j]-c[i]>0。

方法一:

public int longestWPI(int[] hours) {
    HashMap<Integer, Integer> ind = new HashMap<>();//每一种值第一次出现的位置
    HashMap<Integer, Integer> f = new HashMap<>();//每种值最长的序列长度
    ind.put(0,-1);//初始化,前缀和位置0 值为-1,数组的前缀和从位置1开始算
    f.put(0,0);
    int cnt = 0 ;//前缀和
    int ans = 0 ;
    for (int i = 0; i < hours.length; i++) {
        if (hours[i]>8){
            cnt+=1;
        }
        else{
            cnt -=1;
        }
        if(!ind.containsKey(cnt)){
            //没有出现过cnt,cnt的位置就是i
            ind.put(cnt,i);
            if(!ind.containsKey(cnt-1)){
                //没有出现过cnt 而且没有出现过cnt-1,cnt的位置就是i
                f.put(cnt,0);
            }
            else{
                //f.get(n) 代表以n为结尾的最长的序列长度
                //计算f(n)=f(n-1)+pos(n)-pos(n-1)
                int i1 = f.get(cnt - 1) + (i - ind.get(cnt - 1));
                f.put(cnt,i1);
            }
        }
        if(!ind.containsKey(cnt-1)){
            //没有出现过cnt-1,continue
            continue;
        }//否则就出现过cnt-1
        //计算当前f(n)和ans的max
        ans = Math.max(ans,i - ind.get(cnt-1)+f.get(cnt-1));
    }
    return ans;
}

方法二:

public int longestWPI(int[] hours) {
        int sum = 0;
        int res = 0;
        HashMap<Integer, Integer> sumToIndex = new HashMap<>();
        for (int i = 0; i < hours.length; i++){
            if (hours[i] > 8) {
                sum++;
            } else {
                sum--;
            }
            if (sum > 0) {
                res = i + 1;
            }
            else {
                if (!sumToIndex.containsKey(sum)){
                    sumToIndex.put(sum, i);
                }
                if (sumToIndex.containsKey(sum - 1)) {
                    res = Math.max(res, i - sumToIndex.get(sum - 1));
                }
            }
        }
        return res;
    }

tag

sum

posted @ 2021-04-17 11:24  WilliamCui  阅读(86)  评论(0编辑  收藏  举报