6315. Count the Number of Vowel Strings in Range

给你一个下标从 0 开始的字符串数组 words 和两个整数:left 和 right 。

如果字符串以元音字母开头并以元音字母结尾,那么该字符串就是一个 元音字符串 ,其中元音字母是 'a'、'e'、'i'、'o'、'u' 。

返回 words[i] 是元音字符串的数目,其中 i 在闭区间 [left, right] 内。

测试样例

输入:words = ["are","amy","u"], left = 0, right = 2

输出:2

解答:按照题意hard code

class Solution {
    private static final char[] vowels = {'a','e','i','o','u'};

    public int vowelStrings(String[] words, int left, int right) {
        int res = 0;
        for (int i = left; i <= right; ++i) {
            if (isVowel(words[i].charAt(0)) && isVowel(words[i].charAt(words[i].length() - 1))) {
                ++res;
            }
        }
        return res;
    }

    private boolean isVowel(char c) {
        for (char v : vowels) {
            if (c == v) return true;
        }
        return false;
    }
}

6316. Rearrange Array to Maximize Prefix Score

给你一个下标从 0 开始的整数数组 nums 。你可以将 nums 中的元素按 任意顺序 重排(包括给定顺序)。

令 prefix 为一个数组,它包含了 nums 重新排列后的前缀和。换句话说,prefix[i] 是 nums 重新排列后下标从 0 到 i 的元素之和。nums 的 分数 是 prefix 数组中正整数的个数。

返回可以得到的最大分数。

测试样例:

输入:nums = [2,-1,0,1,-3,3,-3]

输出:6

解释:
数组重排为 nums = [2,3,1,-1,-3,0,-3] 。prefix = [2,5,6,5,2,2,-1] ,分数为 6 。可以证明 6 是能够得到的最大分数。

解答: 倒序排序计算为正数的前缀和。我的代码就是顺序排序,计算后缀和。

class Solution {
    public int maxScore(int[] nums) {
        Arrays.sort(nums);
        long sum = 0;
        int res = 0;
        for (int i = nums.length - 1; i >= 0; --i) {
            sum += nums[i];
            if (sum > 0) {
                ++res;
            }
        }
        return res;
    }
}

6317. Count the Number of Beautiful Subarrays

给你一个下标从 0 开始的整数数组nums 。每次操作中,你可以:

  • 选择两个满足 0 <= i, j < nums.length 的不同下标 i 和 j 。
  • 选择一个非负整数 k ,满足 nums[i] 和 nums[j] 在二进制下的第 k 位(下标编号从 0 开始)是 1 。
  • 将 nums[i] 和 nums[j] 都减去 2k 。

如果一个子数组内执行上述操作若干次后,该子数组可以变成一个全为 0 的数组,那么我们称它是一个 美丽 的子数组。

请你返回数组 nums 中 美丽子数组 的数目。

子数组是一个数组中一段连续 非空 的元素序列。

测试样例

输入:nums = [4,3,1,2,4]

输出:2

解释:

nums 中有 2 个美丽子数组:[4,3,1,2,4] 和 [4,3,1,2,4] 。

  • 按照下述步骤,我们可以将子数组 [3,1,2] 中所有元素变成 0 :
    • 选择 [3, 1, 2] 和 k = 1 。将 2 个数字都减去 21 ,子数组变成 [1, 1, 0] 。
    • 选择 [1, 1, 0] 和 k = 0 。将 2 个数字都减去 20 ,子数组变成 [0, 0, 0] 。
  • 按照下述步骤,我们可以将子数组 [4,3,1,2,4] 中所有元素变成 0 :
    • 选择 [4, 3, 1, 2, 4] 和 k = 2 。将 2 个数字都减去 22 ,子数组变成 [0, 3, 1, 2, 0] 。
    • 选择 [0, 3, 1, 2, 0] 和 k = 0 。将 2 个数字都减去 20 ,子数组变成 [0, 2, 0, 2, 0] 。
    • 选择 [0, 2, 0, 2, 0] 和 k = 1 。将 2 个数字都减去 21 ,子数组变成 [0, 0, 0, 0, 0] 。

解答:这道题目是前缀和+计算差值的一个变形。如果能成为一个美丽子数组,则二进制所有位出现次数都是偶数次。换言之,每一位mod值为0。

所以我们可以利用一个Integer来记录每一位的情况,然后用Map记录一下结果就可以了。

class Solution {
    public long beautifulSubarrays(int[] nums) {
        HashMap<Integer, Integer> mem = new HashMap<>();
        mem.put(0, 1);

        int key = 0;
        long res = 0;
        for (int n : nums) {
            for (int i = 0; i < 31; ++i) {
                if (isMark(n, i)) {
                    key = changePos(key, i);
                }
            }
            int tmp = mem.getOrDefault(key, 0);
            res += tmp;
            mem.put(key, tmp + 1);
        }
        return res;
    }

    private boolean isMark(int n, int o) {
        int t = (n >> o) & 1;
        return t == 1;
    }

    private int changePos(int n, int o) {
        int t = (n >> o) & 1;
        if (t == 0) {
            n += (1 << o);
        } else {
            n -= (1 << o);
        }
        return n;
    }
}

6318. Minimum Time to Complete All Tasks

你有一台电脑,它可以 同时 运行无数个任务。给你一个二维整数数组 tasks ,其中 tasks[i] = [starti, endi, durationi] 表示第 i 个任务需要在 闭区间 时间段 [starti, endi] 内运行 durationi 个整数时间点(但不需要连续)。

当电脑需要运行任务时,你可以打开电脑,如果空闲时,你可以将电脑关闭。

请你返回完成所有任务的情况下,电脑最少需要运行多少秒。

测试样例

输入:tasks = [[2,3,1],[4,5,1],[1,5,2]]

输出:2

解释:

  • 第一个任务在闭区间 [2, 2] 运行。
  • 第二个任务在闭区间 [5, 5] 运行。
  • 第三个任务在闭区间 [2, 2] 和 [5, 5] 运行。

电脑总共运行 2 个整数时间点。

解答:按照任务结束时间排序,那么越晚让计算机启动,所能够覆盖的任务越是多。注意提示给的范围:

  • 1 <= tasks.length <= 2000
  • 1 <= starti, endi <= 2000

直接暴力运算就可以了

class Solution {
    public int findMinimumTime(int[][] tasks) {
        Arrays.sort(tasks, (a, b) -> (a[1] - b[1]));
        boolean[] isTaken = new boolean[2001];
        int res = 0;
        for (int[] task : tasks) {
            for (int i = task[0]; i <= task[1]; ++i) {
                if (isTaken[i]) {
                    task[2] -= 1;
                }
            }
            if (task[2] > 0) {
                for (int i = task[1]; i >= task[0]; --i) {
                    if (!isTaken[i]) {
                        isTaken[i] = true;
                        task[2] -= 1;
                        ++res;
                        if (task[2] == 0) break;
                    }
                }
            }
        }
        return res;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *