第 293 场周赛

106 阅读1分钟

题目1:

5234. 移除字母异位词后的结果数组

 显示英文描述 

我的提交返回竞赛

  • 通过的用户数0
  • 尝试过的用户数0
  • 用户总通过次数0
  • 用户总提交次数0
  • 题目难度Easy

给你一个下标从 0 开始的字符串 words ,其中 words[i] 由小写英文字符组成。

在一步操作中,需要选出任一下标 i ,从 words 中 删除 words[i] 。其中下标 i 需要同时满足下述两个条件:

  1. 0 < i < words.length
  2. words[i - 1] 和 words[i] 是 字母异位词 。

只要可以选出满足条件的下标,就一直执行这个操作。

在执行所有操作后,返回 words 。可以证明,按任意顺序为每步操作选择下标都会得到相同的结果。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。例如,"dacb" 是 "abdc" 的一个字母异位词。

 

示例 1:

输入: words = ["abba","baba","bbaa","cd","cd"]
输出: ["abba","cd"]
解释:
获取结果数组的方法之一是执行下述步骤:
- 由于 words[2] = "bbaa" 和 words[1] = "baba" 是字母异位词,选择下标 2 并删除 words[2] 。
  现在 words = ["abba","baba","cd","cd"] 。
- 由于 words[1] = "baba" 和 words[0] = "abba" 是字母异位词,选择下标 1 并删除 words[1] 。
  现在 words = ["abba","cd","cd"] 。
- 由于 words[2] = "cd" 和 words[1] = "cd" 是字母异位词,选择下标 2 并删除 words[2] 。
  现在 words = ["abba","cd"] 。
无法再执行任何操作,所以 ["abba","cd"] 是最终答案。

示例 2:

输入: words = ["a","b","c","d","e"]
输出: ["a","b","c","d","e"]
解释:
words 中不存在互为字母异位词的两个相邻字符串,所以无需执行任何操作。

 

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成

解法:

class Solution {
    /*
    根据题意模拟,遍历数组,如果当前元素和前一个元素是异或word,则删除当前元素
    判断2个word是否是异或work,先转成char数组,排序,再转字符串,equal比较
     */
    public List<String> removeAnagrams(String[] words) {
        List<String> list = Arrays.stream(words).collect(Collectors.toList());
        for (int i = 1; i < list.size(); i++) {
            if (isOrWord(list.get(i), list.get(i - 1))) {
                System.out.println(i);
                list.remove(i);
                i--;
            }
        }
        return list;
    }

    boolean isOrWord(String s1, String s2) {
        char[] s1Char = s1.toCharArray();
        Arrays.sort(s1Char);
        char[] s2Char = s2.toCharArray();
        Arrays.sort(s2Char);
        // System.out.println(s1Char);
        // System.out.println(s2Char);
        // System.out.println(Arrays.toString(s1Char).equals(Arrays.toString(s2Char)));
        return Arrays.toString(s1Char).equals(Arrays.toString(s2Char));
    }
}

题目2

6064. 不含特殊楼层的最大连续楼层数

 显示英文描述 

我的提交返回竞赛

  • 通过的用户数4952
  • 尝试过的用户数5295
  • 用户总通过次数4997
  • 用户总提交次数9299
  • 题目难度Medium

Alice 管理着一家公司,并租用大楼的部分楼层作为办公空间。Alice 决定将一些楼层作为 特殊楼层 ,仅用于放松。

给你两个整数 bottom 和 top ,表示 Alice 租用了从 bottom 到 top(含 bottom 和 top 在内)的所有楼层。另给你一个整数数组 special ,其中 special[i] 表示  Alice 指定用于放松的特殊楼层。

返回不含特殊楼层的 最大 连续楼层数。

 

示例 1:

输入: bottom = 2, top = 9, special = [4,6]
输出: 3
解释: 下面列出的是不含特殊楼层的连续楼层范围:
- (2, 3) ,楼层数为 2 。
- (5, 5) ,楼层数为 1 。
- (7, 9) ,楼层数为 3 。
因此,返回最大连续楼层数 3

示例 2:

输入: bottom = 6, top = 8, special = [7,6,8]
输出: 0
解释: 每层楼都被规划为特殊楼层,所以返回 0

 

提示

  • 1 <= special.length <= 105
  • 1 <= bottom <= special[i] <= top <= 109
  • special 中的所有值 互不相同

解法

class Solution {
    /*
    把bottom和top加入数组,
    取每2个数字差的最大值。注意bottom、top需要包含这一边界条件
     */
    public int maxConsecutive(int bottom, int top, int[] special) {
        Arrays.sort(special);
        List<Integer> list = Arrays.stream(special).boxed().collect(Collectors.toList());
        list.add(0, bottom);
        list.add(list.size(), top);
        int res = 0;
        // System.out.println(list);
        for (int i = 0; i < list.size() - 1; i++) {
            res = Math.max(res, list.get(i + 1) - list.get(i) - ((i + 1 == list.size() - 1 || i == 0) ? 0 : 1));
        }
        return res;
    }
}

题目3

位运算的一个题: leetcode.cn/contest/wee…

题目4

6066. 统计区间中的整数数目

 显示英文描述 

我的提交返回竞赛

  • 通过的用户数489
  • 尝试过的用户数1776
  • 用户总通过次数614
  • 用户总提交次数4520
  • 题目难度Hard

给你区间的  集,请你设计并实现满足要求的数据结构:

  • 新增: 添加一个区间到这个区间集合中。
  • 统计: 计算出现在 至少一个 区间中的整数个数。

实现 CountIntervals 类:

  • CountIntervals() 使用区间的空集初始化对象
  • void add(int left, int right) 添加区间 [left, right] 到区间集合之中。
  • int count() 返回出现在 至少一个 区间中的整数个数。

注意: 区间 [left, right] 表示满足 left <= x <= right 的所有整数 x 。

 

示例 1:

输入
["CountIntervals", "add", "add", "count", "add", "count"]
[[], [2, 3], [7, 10], [], [5, 8], []]
输出
[null, null, null, 6, null, 8]

解释
CountIntervals countIntervals = new CountIntervals(); // 用一个区间空集初始化对象
countIntervals.add(2, 3);  // 将 [2, 3] 添加到区间集合中
countIntervals.add(7, 10); // 将 [7, 10] 添加到区间集合中
countIntervals.count();    // 返回 6
                           // 整数 2 和 3 出现在区间 [2, 3] 中
                           // 整数 7、8、9、10 出现在区间 [7, 10] 中
countIntervals.add(5, 8);  // 将 [5, 8] 添加到区间集合中
countIntervals.count();    // 返回 8
                           // 整数 2 和 3 出现在区间 [2, 3] 中
                           // 整数 5 和 6 出现在区间 [5, 8] 中
                           // 整数 7 和 8 出现在区间 [5, 8] 和区间 [7, 10] 中
                           // 整数 9 和 10 出现在区间 [7, 10] 中

 

提示:

  • 1 <= left <= right <= 109
  • 最多调用  add 和 count 方法 总计 105 次
  • 调用 count 方法至少一次

解法

import java.util.*;
import java.util.stream.Collectors;

public class Problem6066 {
    public static void main(String[] args) {
        CountIntervals obj = new CountIntervals();
        //[[], [2, 3], [7, 10], [], [5, 8], []]
        obj.add(2, 3);
        obj.add(7, 10);
        obj.add(7, 7);
        System.out.println(obj.count());
        obj.add(5, 8);
        System.out.println(obj.count());

    }

    /*
    尝试1:超内存,不能new太大的空间 new boolean[1 * (int)Math.pow(10, 9)]
     */
    static class CountIntervals1 {
        private boolean[] arr = new boolean[1 * (int)Math.pow(10, 9)];

        public CountIntervals1() {

        }

        public void add(int left, int right) {
            for (int i = left; i <= right; i++) {
                arr[i] = true;
            }
        }

        public int count() {
            int res = 0;
            for (int i = 0; i < arr.length; i++) {
                if (arr[i]) {
                    res++;
                }
            }
            return res;
        }
    }

    /*
    尝试2:超内存。

    遇到此case时候:
    ["CountIntervals","count","add","count"]
    [[],[],[1,1000000000],[]]

    set中就需要存1000000000个元素
     */
    static class CountIntervals2 {
        // private boolean[] arr = new boolean[1 * (int)Math.pow(10, 9)];
        private Set<Integer> set = new HashSet<>();

        public CountIntervals2() {

        }

        public void add(int left, int right) {
            for (int i = left; i <= right; i++) {
                set.add(i);
            }
        }

        public int count() {
            return set.size();
        }
    }

    /*
    通过部分用例,看题解说用线段树

    我的解决思路是 区间合并,每次新插入的这个区间和已存在的进行判断合并,移除老区间,插入更长的新区间。
    最后对每个区间长度求和
    但部分用例过不了。。
     */
    static class CountIntervals {
        // private boolean[] arr = new boolean[1 * (int)Math.pow(10, 9)];
        private List<Integer[]> list = new ArrayList<>();

        public CountIntervals() {

        }
        // [[],[2,3],[7,10],[],[5,8],[]]
        public void add(int left, int right) {
            for (int i = 0; i < list.size(); i++) {
                Integer[] itemArr = list.get(i);
                if (!(left > itemArr[1] || right < itemArr[0])) {
                    left = Math.min(left, itemArr[0]);
                    right = Math.max(right, itemArr[1]);
                    // System.out.println(i);
                    list.remove(i);
                    i++;
                }
            }

            list.add(new Integer[] {left, right});
        }

        public int count() {
            int res = 0;
            for (int i = 0; i < list.size(); i++) {
                Integer[] itemArr = list.get(i);
                res += (itemArr[1] - itemArr[0] + 1);
            }
            return res;
        }
    }

    /**
     * Your CountIntervals object will be instantiated and called as such:
     * CountIntervals obj = new CountIntervals();
     * obj.add(left,right);
     * int param_2 = obj.count();
     */
}