• LeetCode高频题:Android系统中WakeLock防止手机进入睡眠模式,统计出每个应用对WakeLock的不同贡献值


    LeetCode高频题:Android系统中WakeLock防止手机进入睡眠模式,统计出每个应用对WakeLock的不同贡献值

    提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
    互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
    你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题
    在这里插入图片描述


    题目

    一个大佬发我的题目,我帮忙看了看
    在这里插入图片描述


    一、审题

    示例:
    在这里插入图片描述
    在这里插入图片描述

    你们有没有觉得案例2有问题啊?
    1245–1250,长度不是6啊
    是5啊
    对吧???????


    二、解题

    这题关键在哪里?

    在俩交叉段中,有交集的你得平均,没有交集的你得算上
    比如上面的案例2

    1236–1238属于两个应用公有的段
    这个只能算平均
    3/2=1

    没有交集的2个2直接加上

    拢共5

    在这里插入图片描述
    但是1245–1250,就是6,没有交集,不平均

    你最重要的就是搞清楚哪些段有交集?

    比如对于当前1234–1240段cur,谁影响了我?
    【影响我是啥意思?就是有的段,它的段尾,竟然>=cur的段首】
    就是影响我cur
    就上面1236–1238段,断尾1238>=cur的段首1234

    那它一定影响cur
    这种情况
    我可以把交集段段首start【就是2段的段首最大值】和断尾end找出来【就是2段的段尾最小值】
    在这里插入图片描述

    没有交集的段首a就是就是2段的段首最小值
    没有交集的段尾b就是就是2段的段尾最大值

    这样的话,贡献值,就是
    start-a+b-end+(end-start)/2
    前面减的是非交集的前面段
    中间减的是非交集的后面段
    最后减的是交集的平均段

    懂?

    具体代码怎么模拟这个过程呢???
    (1)先将所有的时间段变为Node,放入有序表,有序表按照start排序
    (2)然后一鼓作气,把能相互影响的那几段,放入小根堆heap
    (3)一旦有一段压根不想交的进来的话,先不要进堆,结算heap里面的结果,放入ans

    然后回到(2)继续循环就行

    最后ans就出来了

    手撕代码如下:

    import java.util.*;
    
        //看两端交叉,用堆模拟多少人公用
        public static class Solution{
            //应用占用时间段
            public static class Node{
                public int start;
                public int end;
    
                public Node(int s, int e){
                    start = s;
                    end = e;
                }
            }
    
            //排序比较器,根据start排序
            public static class cptr implements Comparator<Node>{
                @Override
                public int compare(Node o1, Node o2){
                    return o1.start - o2.start;
                }
            }
    
            //然后开始模拟业务
            public List<Integer> getWakeLockContrib(List<List<Integer>> arr){
                TreeSet<Node> set = new TreeSet<>(new cptr());//有序表
                for(List<Integer> x:arr){
                    for (int i = 0; i < x.size(); i+=2) {
                        set.add(new Node(x.get(i), x.get(i + 1)));//分别加入set
                    }
                }
                //然后小根堆模拟交集最大的
                PriorityQueue<Node> heap = new PriorityQueue<>(new cptr());//小根堆
                List<Integer> ans = new ArrayList<>();//结果
                while (!set.isEmpty()) {
                    while (heap.isEmpty() ||
                            (!set.isEmpty() && set.first().start <= heap.peek().end)){
                        heap.add(set.pollFirst());//有交集的进来
                    }
                    //不影响影响我cur的,就要结算heap里面的
                    int start = Integer.MIN_VALUE;
                    int end = Integer.MAX_VALUE;
                    int k = 0;
                    int a = Integer.MAX_VALUE;
                    int b = Integer.MIN_VALUE;//这个记录非交叉的部分
                    while (!heap.isEmpty()){
                        k++;//几个共享
                        Node node = heap.poll();
                        start = Math.max(start, node.start);
                        end = Math.min(end, node.end);//取交集
                        a = Math.min(a, node.start);//取非交集
                        b = Math.max(b, node.end);
                    }
                    if (start != Integer.MIN_VALUE && end != Integer.MAX_VALUE){
                        ans.add(b - end + start - a + (end - start) / k);//加入结果
                    }
                }
                //最后一定会返回结果
                return ans;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    然后测试:

    案例1:

        public static void main(String[] args) {
            List<List<Integer>> arr = new ArrayList<>();
            List<Integer> tmp = new ArrayList<>();
            tmp.add(1234);
            tmp.add(1235);
            arr.add(tmp);
            tmp = new ArrayList<>();
            tmp.add(1236);
            tmp.add(1238);
            arr.add(tmp);
    
            Solution solution = new Solution();
            List<Integer> ans = solution.getWakeLockContrib(arr);
            for(Integer x:ans) System.out.println(x +" ");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:
    在这里插入图片描述

    案例2:

        public static void main(String[] args) {
            List<List<Integer>> arr = new ArrayList<>();
            List<Integer> tmp = new ArrayList<>();
            tmp.add(1234);
            tmp.add(1240);
            arr.add(tmp);
            tmp = new ArrayList<>();
            tmp.add(1236);
            tmp.add(1238);
            tmp.add(1245);
            tmp.add(1250);
            arr.add(tmp);
    
            Solution solution = new Solution();
            List<Integer> ans = solution.getWakeLockContrib(arr);
            for(Integer x:ans) System.out.println(x +" ");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    结果:
    在这里插入图片描述

    非常稳
    笔试过程中,可能:会出bug,想想逻辑,调试一下就知道自己错哪里了,慢慢就调试出来了


    总结

    提示:重要经验:

    1)贪心的题目,一般就是排序+堆,典型的这种操作,大厂经常考,据说这个是OPPO23届秋招的题目
    3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

  • 相关阅读:
    数据结构题型9-顺序栈
    【无标题】
    20221104英语学习
    《LeetCode力扣练习》代码随想录——字符串(KMP算法学习补充——针对next数组构建的回退步骤进行解释)
    MongoDB差异数据对比的快速指南
    LeetCode | 218. 天际线问题
    K_A02_006 基于单片机驱动四位 数码管显示动态静态滚动显示
    东郊到家app小程序公众号软件开发预约同城服务系统成品源码部署
    redisson中的分布式锁二
    C++ STL进阶与补充(vector容器)
  • 原文地址:https://blog.csdn.net/weixin_46838716/article/details/126660031