LeetCode 693. 交替位二进制数 / 2024. 考试的最大困扰度 / 1606. 找到处理最多请求的服务器

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 693. 交替位二进制数 / 2024. 考试的最大困扰度 / 1606. 找到处理最多请求的服务器相关的知识,希望对你有一定的参考价值。

693. 交替位二进制数

2022.3.28 每日一题

题目描述

给定一个正整数,检查它的二进制表示是否总是 0、1 交替出现:换句话说,就是二进制表示中相邻两位的数字永不相同。

示例 1:

输入:n = 5
输出:true
解释:5 的二进制表示是:101

示例 2:

输入:n = 7
输出:false
解释:7 的二进制表示是:111.

示例 3:

输入:n = 11
输出:false
解释:11 的二进制表示是:1011.

提示:

1 <= n <= 2^31 - 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-number-with-alternating-bits
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

class Solution 
    public boolean hasAlternatingBits(int n) 
        //直接用位运算的方法
        //首先,n向右移动一位以后,与原来的数相与,就是都是1了
        //然后怎么判断这个数都是1呢,就是 x 与 x + 1 相与,如果都是0,那么说明都是1
        int t = n ^ (n >> 1);
        //System.out.println(t);
        return (t & (t + 1)) == 0;
    

2024. 考试的最大困扰度

2022.3.29 每日一题

题目描述

一位老师正在出一场由 n 道判断题构成的考试,每道题的答案为 true (用 ‘T’ 表示)或者 false (用 ‘F’ 表示)。老师想增加学生对自己做出答案的不确定性,方法是 最大化 有 连续相同 结果的题数。(也就是连续出现 true 或者连续出现 false)。

给你一个字符串 answerKey ,其中 answerKey[i] 是第 i 个问题的正确结果。除此以外,还给你一个整数 k ,表示你能进行以下操作的最多次数:

  • 每次操作中,将问题的正确答案改为 ‘T’ 或者 ‘F’ (也就是将 answerKey[i] 改为 ‘T’ 或者 ‘F’ )。

请你返回在不超过 k 次操作的情况下,最大 连续 ‘T’ 或者 ‘F’ 的数目。

示例 1:

输入:answerKey = “TTFF”, k = 2
输出:4
解释:我们可以将两个 ‘F’ 都变为 ‘T’ ,得到 answerKey = “TTTT” 。
总共有四个连续的 ‘T’ 。

示例 2:

输入:answerKey = “TFFT”, k = 1
输出:3
解释:我们可以将最前面的 ‘T’ 换成 ‘F’ ,得到 answerKey = “FFFT” 。
或者,我们可以将第二个 ‘T’ 换成 ‘F’ ,得到 answerKey = “TFFF” 。
两种情况下,都有三个连续的 ‘F’ 。

示例 3:

输入:answerKey = “TTFTTFTT”, k = 1
输出:5
解释:我们可以将第一个 ‘F’ 换成 ‘T’ ,得到 answerKey = “TTTTTFTT” 。
或者我们可以将第二个 ‘F’ 换成 ‘T’ ,得到 answerKey = “TTFTTTTT” 。
两种情况下,都有五个连续的 ‘T’ 。

提示:

n == answerKey.length
1 <= n <= 5 * 10^4
answerKey[i] 要么是 ‘T’ ,要么是 ‘F’
1 <= k <= n
通过次数32,372提交次数56,404

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximize-the-confusion-of-an-exam
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

自己写了个滑动窗口,不知道当时怎么想的,非要一段一段连续的处理
然后就陷入了魔鬼细节中,改了好多次过的

class Solution 
    public int maxConsecutiveAnswers(String answerKey, int k) 
        //直接遍历统计个数就行了
        //相当于一个滑动窗口吧,只不过这个窗口大小是根据这个字符串变化的
        int count = 0;
        char last = ' ';
        List<Integer> list = new ArrayList<>();
        //先统计个数
        if(answerKey.length() <= k)
            return answerKey.length();
        for(char c : answerKey.toCharArray())
            if(last != c)
                last = c;
                list.add(count);
                count = 1;
            else
                count++;
            
        
        list.add(count);
        list.remove(0);
        //System.out.println(list.size());
        //System.out.println(list.get(0));
        int left = 0;
        int right = 1;
        int l = list.size();
        int temp = list.get(0);
        int max = temp;
        while(right < l)
            int kk = k;
            while(right < l && list.get(right) <= kk)
                temp += list.get(right);
                kk -= list.get(right);
                temp += right + 1 < l ? list.get(right + 1) : 0;
                right += 2; 
            
            //如果不能加整段,那么只能加一部分
            if(right < l)
                temp += kk;
            //如果到了最后了,但是还有剩余,那么就在前面一段中加
            
            else if(left > 0)
                temp += list.get(left - 1) > kk ? kk : list.get(left - 1);
            
            max = Math.max(max, temp);
            if(right >= l)
                break;
            left += 1;
            temp = list.get(left);
            right = left + 1;
        
        //System.out.println(max);
        temp = list.get(l - 1);
        for(int i = l - 2; i >= 0 && k > 0; i -= 2)
            if(list.get(i) < k)
                temp += list.get(i);
                k -= list.get(i);
                temp += i > 0 ? list.get(i - 1) : 0;
            
            else
                temp += k;
                k = 0;
            
            
        
        max = Math.max(max, temp);
        return max;
    

后面发现一个一个字符处理更加简单方便

class Solution 
    //直接一个字符一个字符的滑动就可以了,如果另一个字符的个数大于k了,那么就把左端点移动
    public int maxConsecutiveAnswers(String answerKey, int k) 
        return Math.max(maxConsecutiveChar(answerKey, k, 'T'), maxConsecutiveChar(answerKey, k, 'F'));
    

    public int maxConsecutiveChar(String answerKey, int k, char ch) 
        int n = answerKey.length();
        int ans = 0;
        for (int left = 0, right = 0, sum = 0; right < n; right++) 
            sum += answerKey.charAt(right) != ch ? 1 : 0;
            while (sum > k) 
                sum -= answerKey.charAt(left++) != ch ? 1 : 0;
            
            ans = Math.max(ans, right - left + 1);
        
        return ans;
    

1606. 找到处理最多请求的服务器

2022.3.30 每日一题

题目描述

你有 k 个服务器,编号为 0 到 k-1 ,它们可以同时处理多个请求组。每个服务器有无穷的计算能力但是 不能同时处理超过一个请求 。请求分配到服务器的规则如下:

  • 第 i (序号从 0 开始)个请求到达。
  • 如果所有服务器都已被占据,那么该请求被舍弃(完全不处理)。
  • 如果第 (i % k) 个服务器空闲,那么对应服务器会处理该请求。
    = 否则,将请求安排给下一个空闲的服务器(服务器构成一个环,必要的话可能从第 0 个服务器开始继续找下一个空闲的服务器)。比方说,如果第 i 个服务器在忙,那么会查看第 (i+1) 个服务器,第 (i+2) 个服务器等等。

给你一个 严格递增 的正整数数组 arrival ,表示第 i 个任务的到达时间,和另一个数组 load ,其中 load[i] 表示第 i 个请求的工作量(也就是服务器完成它所需要的时间)。你的任务是找到 最繁忙的服务器 。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。

请你返回包含所有 最繁忙服务器 序号的列表,你可以以任意顺序返回这个列表。

示例 1:


输入:k = 3, arrival = [1,2,3,4,5], load = [5,2,3,3,3]
输出:[1]
解释:
所有服务器一开始都是空闲的。
前 3 个请求分别由前 3 台服务器依次处理。
请求 3 进来的时候,服务器 0 被占据,所以它被安排到下一台空闲的服务器,也就是服务器 1 。
请求 4 进来的时候,由于所有服务器都被占据,该请求被舍弃。
服务器 0 和 2 分别都处理了一个请求,服务器 1 处理了两个请求。所以服务器 1 是最忙的服务器。

示例 2:

输入:k = 3, arrival = [1,2,3,4], load = [1,2,1,2]
输出:[0]
解释:
前 3 个请求分别被前 3 个服务器处理。
请求 3 进来,由于服务器 0 空闲,它被服务器 0 处理。
服务器 0 处理了两个请求,服务器 1 和 2 分别处理了一个请求。所以服务器 0 是最忙的服务器。

示例 3:

输入:k = 3, arrival = [1,2,3], load = [10,12,11]
输出:[0,1,2]
解释:每个服务器分别处理了一个请求,所以它们都是最忙的服务器。

示例 4:

输入:k = 3, arrival = [1,2,3,4,8,9,10], load = [5,2,10,3,1,2,2]
输出:[1]

示例 5:

输入:k = 1, arrival = [1], load = [1]
输出:[0]

提示:

1 <= k <= 10^5
1 <= arrival.length, load.length <= 10^5
arrival.length == load.length
1 <= arrival[i], load[i] <= 10^9
arrival 保证 严格递增 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-servers-that-handled-most-number-of-requests
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

和华为之前秋招的笔试题很类似,这里多了一个服务器的环,需要找环中下一个空闲服务器,而不是直接找最小编号的服务器处理,不算难

class Solution 
    public List<Integer> busiestServers(int k, int[] arrival, int[] load) 
        //有点类似华为的笔试题
        //这个题有个什么问题呢,就是进来的请求需要按环找下一个空闲服务器处理
        //想想这个该怎么办
        //需要有一个集合放置空闲的服务器,并且这个集合还是按照大小排序的,那么就想到了TreeMap


        //k个服务器处理的请求数目
        int[] count = new int[k];
        //放置空闲服务器,且按从小到大排序
        TreeSet<Integer> free = new TreeSet<>();
        //int[] 两个参数,一个服务器编号,一个空闲时间,按照空闲时间排序
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> (a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]));

        //先将所有的服务器放在set中
        for(int i = 0; i < k; i++)
            free.add(i);
        
        int l = arrival.length;
        for(int i = 0; i < l; i++)
            int time = arrival[i];
            //到达这个时间,如果有空闲的服务器,先放到set中
            while(!pq.isEmpty() && pq.peek()[1] <= time)
                int f = pq.poll()[0];
                free.add(f);
            
            int spend = load[i];
            //需要第几个服务器
            int need = i % k;
            //找下一个空闲服务器
            Integer realNeed = free.ceiling(need);
            //如果找不到比它大的同时也没有比它小的
            if(realNeed == null && free.isEmpty())
                continue;
            if(realNeed == null)
                realNeed = free.first();
            pq.offer(new int[]realNeed, time + spend);
            count[realNeed]++;
            free.remove(realNeed);
        
        List<Integer> res = new ArrayList<>();
        int max = count[0];
        res.add(0);
        for(int i = 1; i < k; i++)
            if(count[i] > max)
                res.clear();
                max = count[i];
                res.add(i);
            else if(count[i] == max)
                res.add(i);
            
        
        return res;
    

python学习中
这里需要注意,busy作为一个优先队列,默认是按照第一个下标排序的

from sortedcontainers import SortedList

class Solution:
    def busiestServers(self, k: int, arrival: List[int], load: List[int]) -> List[int]:
        count = [0] * k
        l = len(arrival)
        busy = []
        free = SortedList(range(k))
        for i in range(l):
            time = arrival[i]
            spend = load[i]
            while busy and busy[0][0] <= time:
                free.add(busy[0][1])
                heappop(busy)
            if len(free) == 0:
                continue
            need = free.bisect_left(i % k)
            if need == len(free):
                need = 0
            idx = free[need]
            count[idx] += 1
            heappush(busy, (time + spend, idx))
            free.remove(idx)
        maxf = max(count)
        return [i for i in range(k) if count[i] == maxf]

以上是关于LeetCode 693. 交替位二进制数 / 2024. 考试的最大困扰度 / 1606. 找到处理最多请求的服务器的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 693. 交替位二进制数 / 2024. 考试的最大困扰度 / 1606. 找到处理最多请求的服务器

693. 交替位二进制数

LC-693 交替位二进制数

「 每日一练,快乐水题 」693. 交替位二进制数

「 每日一练,快乐水题 」693. 交替位二进制数

剑指 Offer 15. 二进制中1的个数693. 交替位二进制数