LeetCode第221场周赛

LeetCode第221场周赛

题目:1704. 判断字符串的两半是否相似

给你一个偶数长度的字符串 s 。将其拆分成长度相同的两半,前一半为 a ,后一半为 b 。

两个字符串 相似 的前提是它们都含有相同数目的元音(‘a’,‘e’,‘i’,‘o’,‘u’,‘A’,‘E’,‘I’,‘O’,‘U’)。注意,s 可能同时含有大写和小写字母。

如果 a 和 b 相似,返回 true ;否则,返回 false 。

示例 1:

输入:s = “book”
输出:true
解释:a = “bo” 且 b = “ok” 。a 中有 1 个元音,b 也有 1 个元音。所以,a 和 b 相似。
示例 2:

输入:s = “textbook”
输出:false
解释:a = “text” 且 b = “book” 。a 中有 1 个元音,b 中有 2 个元音。因此,a 和 b 不相似。
注意,元音 o 在 b 中出现两次,记为 2 个。
示例 3:

输入:s = “MerryChristmas”
输出:false
示例 4:

输入:s = “AbCdEfGh”
输出:true

提示:

2 <= s.length <= 1000
s.length 是偶数
s 由 大写和小写 字母组成

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

思路:简单模拟

因为字符串是由大小字母构成,为了方便处理我们统一转成小写字母。

然后将字符串分成a b两段,分别统计一下元音字母的数量。


class Solution {
    public boolean halvesAreAlike(String s) {
        Set<Character> set = new HashSet<>();
        set.add('a');
        set.add('e');
        set.add('i');
        set.add('o');
        set.add('u');
        s = s.toLowerCase();
        int a = 0;
        int b = 0;
        for(int i = 0 , j = s.length() - 1; i < j; i++, j--) {
            if(set.contains(s.charAt(i))) a++;
            if(set.contains(s.charAt(j))) b++;
        }
        return a == b;
    }
}

题目:1705. 吃苹果的最大数目

有一棵特殊的苹果树,一连 n 天,每天都可以长出若干个苹果。在第 i 天,树上会长出 apples[i] 个苹果,这些苹果将会在 days[i] 天后(也就是说,第 i + days[i] 天时)腐烂,变得无法食用。也可能有那么几天,树上不会长出新的苹果,此时用 apples[i] == 0 且 days[i] == 0 表示。

你打算每天 最多 吃一个苹果来保证营养均衡。注意,你可以在这 n 天之后继续吃苹果。

给你两个长度为 n 的整数数组 days 和 apples ,返回你可以吃掉的苹果的最大数目。

示例 1:

输入:apples = [1,2,3,5,2], days = [3,2,1,4,2]
输出:7
解释:你可以吃掉 7 个苹果:

  • 第一天,你吃掉第一天长出来的苹果。
  • 第二天,你吃掉一个第二天长出来的苹果。
  • 第三天,你吃掉一个第二天长出来的苹果。过了这一天,第三天长出来的苹果就已经腐烂了。
  • 第四天到第七天,你吃的都是第四天长出来的苹果。
    示例 2:

输入:apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2]
输出:5
解释:你可以吃掉 5 个苹果:

  • 第一天到第三天,你吃的都是第一天长出来的苹果。
  • 第四天和第五天不吃苹果。
  • 第六天和第七天,你吃的都是第六天长出来的苹果。

提示:

apples.length == n
days.length == n
1 <= n <= 2 * 104
0 <= apples[i], days[i] <= 2 * 104
只有在 apples[i] = 0 时,days[i] = 0 才成立

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

思路:贪心+优先队列

这题好气啊,思路是没错的但在比赛的时候code写错了。

贪心策略:优先吃最先坏掉的

优先队列存多久过期和有多少个苹果,按照过期时间比较。

当队列中有苹果,我们优先吃掉最先坏掉的。但没有苹果我们就不吃,直接进入下一天,看一下有没有新的苹果。

在每次吃苹果前先将所有过期的苹果从队列中移除。但在n天之后我们还可一吃萍果,所以我们还需将队列中剩余的苹果在吃掉(将能吃的吃掉)。

class Solution {
    class zip implements Comparable<zip> {
        int x, y;

        public zip(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int compareTo(zip o) {
            return this.x - o.x;
        }
    }

    public int eatenApples(int[] apples, int[] days) {
        PriorityQueue<zip> que = new PriorityQueue<>();
        int n = apples.length;
        int ans = 0;
        for(int i = 0; i < n; i++) {
            que.add(new zip(days[i] + i - 1, apples[i]));
            while(!que.isEmpty() && que.peek().x < i) que.poll();
            if(!que.isEmpty()){
                zip cur = que.poll();
                cur.y--;
                ans++;
                if(cur.y > 0 && cur.x > i) que.add(cur);
            }
        }
        while(!que.isEmpty()){
            while(!que.isEmpty() && que.peek().x < n) que.poll();
            if(!que.isEmpty()){
                zip cur = que.poll();
                cur.y--;
                ans++;
                if(cur.y > 0 && cur.x > n) que.add(cur);
            }
            n++;
        }
        return ans;
    }
}

题目:1706. 球会落何处

用一个大小为 m x n 的二维网格 grid 表示一个箱子。你有 n 颗球。箱子的顶部和底部都是开着的。

箱子中的每个单元格都有一个对角线挡板,跨过单元格的两个角,可以将球导向左侧或者右侧。

将球导向右侧的挡板跨过左上角和右下角,在网格中用 1 表示。
将球导向左侧的挡板跨过右上角和左下角,在网格中用 -1 表示。
在箱子每一列的顶端各放一颗球。每颗球都可能卡在箱子里或从底部掉出来。如果球恰好卡在两块挡板之间的 “V” 形图案,或者被一块挡导向到箱子的任意一侧边上,就会卡住。

返回一个大小为 n 的数组 answer ,其中 answer[i] 是球放在顶部的第 i 列后从底部掉出来的那一列对应的下标,如果球卡在盒子里,则返回 -1 。

示例 1:

输入:grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
输出:[1,-1,-1,-1,-1]
解释:示例如图:
b0 球开始放在第 0 列上,最终从箱子底部第 1 列掉出。
b1 球开始放在第 1 列上,会卡在第 2、3 列和第 1 行之间的 “V” 形里。
b2 球开始放在第 2 列上,会卡在第 2、3 列和第 0 行之间的 “V” 形里。
b3 球开始放在第 3 列上,会卡在第 2、3 列和第 0 行之间的 “V” 形里。
b4 球开始放在第 4 列上,会卡在第 2、3 列和第 1 行之间的 “V” 形里。
示例 2:

输入:grid = [[-1]]
输出:[-1]
解释:球被卡在箱子左侧边上。

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 100
grid[i][j] 为 1 或 -1

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

思路:模拟

题目给的数据范围不是很大,所以可以模拟一下每个球走的路径。

至于怎么模拟,对于每个格子的挡板,我们假设成把小球往左或者往右引,至于小球能否走到下一格就需要判断,小球走的方向是否有东西将它挡住。

分析: grid[i, j]

  • 如果 =1 则将球导向右侧 当小球的右侧超出二维网格或-1(与grid[i, j]方向相反)是小球被挡住
  • 如果 =-1 则将球导向左侧 当小球的左侧超出二维网格或1(与grid[i, j]方向相反)是小球被挡住
class Solution {
    public int[] findBall(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        int[] ans = new int[m];
        for(int k = 0; k < m; k++) {
            int j = k;
            boolean flag = true;
            for(int i = 0; i < n; i++) {
                int j1 = grid[i][j] + j;
                if(j1 == -1 || j1 == m || grid[i][j] + grid[i][j1] == 0) {
                    flag = false;
                    ans[k] = -1;
                    break;
                }
                j = j1;
            }
            if(flag)
            ans[k] = j;
        }
        return ans;
    }
}

题目:1707. 与数组中元素的最大异或值

给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。

第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。

返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。

示例 1:

输入:nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
输出:[3,3,7]
解释:

  1. 0 和 1 是仅有的两个不超过 1 的整数。0 XOR 3 = 3 而 1 XOR 3 = 2 。二者中的更大值是 3 。
  2. 1 XOR 2 = 3.
  3. 5 XOR 2 = 7.
    示例 2:

输入:nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
输出:[15,-1,5]

提示:

1 <= nums.length, queries.length <= 105
queries[i].length == 2
0 <= nums[j], xi, mi <= 109

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

思路:字典树+离线思想

查找一个数在一个数集中的最大异或和。

策略:异或是将两个数相同为0不同为1,所以对于这个数我们尽可的找与它各位二进制数不同的数。

我们将这个数集中数,做成一棵二进制树,然后通过上面的策略找就行了。

而这题我们将两个数组排个序,每次将小于需查询的mi的数加入到树中,然后查找最大异或和。

class Solution {
    class tree{
        tree[] next;
        int end;
        public tree(){
            end = 0;
            next = new tree[2];
        }
    }
    tree root;

    public int[] maximizeXor(int[] nums, int[][] queries) {
        root = new tree();
        int n = queries.length, m = nums.length;
        int[] ans = new int[n];
        int[][] qq = new int[n][3];
        for(int i = 0; i < n; i++) {
            qq[i][0] = queries[i][0];
            qq[i][1] = queries[i][1];
            qq[i][2] = i;
        }
        Arrays.sort(nums);
        Arrays.sort(qq, (o1, o2) -> o1[1] - o2[1]);

        int j = 0;
        for(int i = 0; i < n; i++) {
            while(j < m && nums[j] <= qq[i][1]) {
                add(nums[j++]);
            }
            ans[qq[i][2]] = find(qq[i][0]);
        }

        return ans;
    }

    private int find(int num){
        tree p = root;
        for(int i = 31; i >= 0; i--) {
            int x = (num >> i) & 1;
            if(p.next[1 - x] != null) p = p.next[1 - x];
            else if(p.next[x] != null) p = p.next[x];
            else return -1;
        }
        return num ^ p.end;
    }

    private void add(int num) {
        tree p = root;
        for(int i = 31; i >= 0; i--) {
            int x = (num >> i) & 1;
            if(p.next[x] == null) p.next[x] = new tree();
            p = p.next[x];
        }
        p.end = num;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值