Leetcode刷题 2021.04.19

Leetcode刷题 2021.04.19

  • Leetcode1832 判断句子是否为全字母句
  • Leetcode1833 雪糕的最大数量
  • Leetcode1834 最小公共区域
  • Leetcode1835 所有数对按位与结果的异或和
  • Leetcode1827 最少操作使数组递增
  • Leetcode1828 统计一个圆中点的数目
  • Leetcode1829 每个查询的最大异或值

Leetcode1832 判断句子是否为全字母句

全字母句 指包含英语字母表中每个字母至少一次的句子。

给你一个仅由小写英文字母组成的字符串 sentence ,请你判断 sentence 是否为 全字母句 。

如果是,返回 true ;否则,返回 false 。

好久没更新博客了,倒不是因为懒。实在是刷到现在每天再做三道新题已经比较困难了。最近这段时间也都是被毕业和工作的事情压着,每周能有时间搞搞周赛已经很不错了。最近又被几家大厂待定了,今天突然有看开的感觉了。可能是因为天气好的原因,心情也跟着好了起来。不管怎么样,把自己能做到的做到就好了。

周赛第一题,用一个数组记录一下就好了,简单题。

class Solution {
     
    public boolean checkIfPangram(String sentence) {
     
        int[] map = new int[26];
        for(char c : sentence.toCharArray()){
     
            map[c - 'a']++;
        }
        for(int i = 0; i < map.length; i++){
     
            if (map[i] == 0) return false;
        }
        return true;
    }
}

Leetcode1833 雪糕的最大数量

夏日炎炎,小男孩 Tony 想买一些雪糕消消暑。

商店中新到 n 支雪糕,用长度为 n 的数组 costs 表示雪糕的定价,其中 costs[i] 表示第 i 支雪糕的现金价格。Tony 一共有 coins 现金可以用于消费,他想要买尽可能多的雪糕。

给你价格数组 costs 和现金量 coins ,请你计算并返回 Tony 用 coins 现金能够买到的雪糕的 最大数量 。

注意:Tony 可以按任意顺序购买雪糕。

复盘的时候看到雪糕,突然想吃雪糕了,等下去买根吃吧。这题一开始以为是dp,后来觉得简单贪心就好了,也是比较简单的。

class Solution {
     
    public int maxIceCream(int[] costs, int coins) {
     
        Arrays.sort(costs);
        int res = 0, i = 0;
        while (i < costs.length){
     
            coins -= costs[i++];
            if (coins < 0) break;
            res++;
        }

        return res;
    }
}

Leetcode1834 最小公共区域

给你一个二维数组 tasks ,用于表示 n​​​​​​ 项从 0 到 n - 1 编号的任务。其中 tasks[i] = [enqueueTimei, processingTimei] 意味着第 i​​​​​​​​​​ 项任务将会于 enqueueTimei 时进入任务队列,需要 processingTimei 的时长完成执行。

现有一个单线程 CPU ,同一时间只能执行 最多一项 任务,该 CPU 将会按照下述方式运行:

如果 CPU 空闲,且任务队列中没有需要执行的任务,则 CPU 保持空闲状态。
如果 CPU 空闲,但任务队列中有需要执行的任务,则 CPU 将会选择 执行时间最短 的任务开始执行。如果多个任务具有同样的最短执行时间,则选择下标最小的任务开始执行。
一旦某项任务开始执行,CPU 在 执行完整个任务 前都不会停止。
CPU 可以在完成一项任务后,立即开始执行一项新任务。
返回 CPU 处理任务的顺序。

这题思路是不难的,但是编写的时候要考虑一下各种情况。思路其实就是模拟,用一个堆保存当前可以执行的任务,从中取出最小就行了。实际上感觉就是最短作业优先的实现。

class Solution {
     
    class Node{
     
        int index;
        int start;
        int time;

        public Node(int index, int start, int time){
     
            this.index = index;
            this.start = start;
            this.time = time;
        }
    }
    public int[] getOrder(int[][] tasks) {
     
        int n = tasks.length, i = 0, idx = 0;
        int[] res = new int[n];
        Node[] help = new Node[n];
        //用一个Node保存
        for(int j = 0; j < n; j++){
     
            help[j] = new Node(j, tasks[j][0], tasks[j][1]);
        }
        //对Node的开始时间排序
        Arrays.sort(help, (x, y) -> (x.start - y.start));
		//堆里先按需要的作业时间排序,再按下标排序
        PriorityQueue<Node> queue = new PriorityQueue<>((x, y) -> (x.time == y.time ? x.index - y.index : x.time - y.time));
        int now = 1;
        while (i < n || !queue.isEmpty()){
     
        	//如果说当前时间小于后一个开始时间,就更新时间为后一个开始时间
            if (queue.isEmpty() && i < n && help[i].start > now){
     
                now = help[i].start;
            }
            //小于当前时间的都能入队
            while (i < n && help[i].start <= now){
     
                queue.offer(help[i]);
                i++;
            }
            //从队里取出最短作业的任务,更新一下时间
            if (!queue.isEmpty()){
     
                Node temp = queue.poll();
                res[idx++] = temp.index;
                if (now + temp.time >= now){
     
                    now = now + temp.time;
                }
            }
        }
        return res;
    }
}

Leetcode1835 所有数对按位与结果的异或和

列表的 异或和(XOR sum)指对所有元素进行按位 XOR 运算的结果。如果列表中仅有一个元素,那么其 异或和 就等于该元素。

例如,[1,2,3,4] 的 异或和 等于 1 XOR 2 XOR 3 XOR 4 = 4 ,而 3 的 异或和 等于 3 。
给你两个下标 从 0 开始 计数的数组 arr1 和 arr2 ,两数组均由非负整数组成。

根据每个 (i, j) 数对,构造一个由 arr1[i] AND arr2[j](按位 AND 运算)结果组成的列表。其中 0 <= i < arr1.length 且 0 <= j < arr2.length 。

返回上述列表的 异或和 。

难得一道很简单的hard题,最多就是medium感觉。首先看数据范围肯定不能暴力,然后可以利用异或运算的分配率,先算一下arr2的异或和,在和arr1的每一个元素做与运算后再异或就行了。

class Solution {
     
    public int getXORSum(int[] arr1, int[] arr2) {
     
        int sum = 0;
        //先算下arr2的异或和
        for(int num : arr2){
     
            sum ^= num;
        }
        int res = 0;
        //再和arr1的每一个元素做与运算,再异或
        for(int num : arr1){
     
            res ^= (num & sum);
        }
        return res;
    }
}

Leetcode1827 最少操作使数组递增

给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。

比方说,如果 nums = [1,2,3] ,你可以选择增加 nums1 得到 nums = [1,3,3] 。
请你返回使 nums 严格递增 的 最少 操作次数。

我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况。

简单题,因为只能做递增运算,所以吐过当前数大于之前的元素就不变,否则加到之前元素加1就行了。

class Solution {
     
    public int minOperations(int[] nums) {
     
        int n = nums.length, res = 0, prev = nums[0];
        for(int i = 1; i < n; i++){
     
            if (nums[i] <= prev){
     
                res += prev + 1 - nums[i];
                prev = prev + 1;        
            }else{
     
                prev = nums[i];   
            }
        }
        
        return res;
    }
}

Leetcode1828 统计一个圆中点的数目

给你一个数组 points ,其中 points[i] = [xi, yi] ,表示第 i 个点在二维平面上的坐标。多个点可能会有 相同 的坐标。

同时给你一个数组 queries ,其中 queries[j] = [xj, yj, rj] ,表示一个圆心在 (xj, yj) 且半径为 rj 的圆。

对于每一个查询 queries[j] ,计算在第 j 个圆 内 点的数目。如果一个点在圆的 边界上 ,我们同样认为它在圆 内 。

请你返回一个数组 answer ,其中 answer[j]是第 j 个查询的答案

也是简单题,根据数据范围,算下每个点到圆心的距离,然后和半径比一下就行了。


class Solution {
     
    public int[] countPoints(int[][] points, int[][] queries) {
     
        int n = queries.length, index = 0;
        int[] res = new int[n];
        for(int[] query : queries){
     
            int x1 = query[0], y1 = query[1], count = 0;
            for(int[] point : points){
     
                int x2 = point[0], y2 = point[1];
                double dist = distance(x1, y1, x2, y2);
                if (dist <= query[2]){
     
                    count++;
                }
            }
            res[index++] = count;
        }
        return res;
    }

    private double distance(int x1, int y1, int x2, int y2){
     
        int temp = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
        return Math.sqrt(temp);
    }
}

Leetcode1829 每个查询的最大异或值

给你一个 有序 数组 nums ,它由 n 个非负整数组成,同时给你一个整数 maximumBit 。你需要执行以下查询 n 次:

找到一个非负整数 k < 2maximumBit ,使得 nums[0] XOR nums1 XOR … XOR nums[nums.length-1] XOR k 的结果 最大化 。k 是第 i 个查询的答案。
从当前数组 nums 删除 最后 一个元素。
请你返回一个数组 answer ,其中 answer[i]是第 i 个查询的结果。

这题一开始看到删除,以为要先保存异或前缀。其实不用,从后往前填答案即可。然后想一想不大于给定maximumBit的数,一定可以使得当前异或的结果的后几位取反,那么贪心地把小于maximumBit的低位都取反就行了。

class Solution {
     
    public static int[] getMaximumXor(int[] nums, int maximumBit) {
     
        int n = nums.length;
        int[] help = new int[n];
        int[] res = new int[n];
        int sum = 0;
        //前缀异或,其实不需要
        for(int i = 0; i < nums.length; i++){
     
            sum ^= nums[i];
            help[i] = sum;
        }
        int index = 0;
        for(int i = n - 1; i >= 0; i--){
     
            int temp = 0;
            for(int j = 31; j >= 0; j--){
     
                int shift = ((help[i] >> j) & 1);
                //高位都不动,低位取反即可
                if (j >= maximumBit){
     
                    temp += shift * (1 << j);
                }else{
     
                    temp += (shift ^ 1) * (1 << j);
                }
            }
            res[index++] = temp;
        }

        return res;
    }
}

你可能感兴趣的:(刷题)