【leetcode周赛总结】LeetCode第293场周赛总结(5.16)

Problem A - 移除字母异位词后的结果数组

思路

按照题目意思模拟,实现判断是否是异位词的函数,用两个长度26的数组统计。

代码

class Solution {
    public List<String> removeAnagrams(String[] words) {
        List<String> res = new ArrayList<>();
        String last = words[0];
        res.add(last);
        int n = words.length;
        for(int i=1;i<n;i++){
            if(!isAnagram(last,words[i])){
                res.add(words[i]);
                last = words[i];
            }
        }
        return res;
    }
    private boolean isAnagram(String s, String t) {
        if(s.length() != t.length())
            return false;
        int[] alpha = new int[26];
        for(int i = 0; i< s.length(); i++) {
            alpha[s.charAt(i) - 'a'] ++;
            alpha[t.charAt(i) - 'a'] --;
        }
        for(int i=0;i<26;i++)
            if(alpha[i] != 0)
                return false;
        return true;
    }
}

Problem B - 不含特殊楼层的最大连续楼层数

思路

思路1、遍历special,维护一个begin和ans

思路2、

把 bottom - 1 和 top + 1 也看作特殊楼层加入 special 中,然后将 special 排序。答案就是 special 中相邻元素之差的最大值减一。

作者:TsReaper
链接:https://leetcode.cn/circle/discuss/sKLBSg/
 

代码

思路1

class Solution {
    public int maxConsecutive(int bottom, int top, int[] special) {
        int res = 0;
        int begin=bottom;
        Arrays.sort(special);
        for(int s:special){
            if(s!=begin && begin<=top){
                res = Math.max(res,s-begin);
            }
            begin = s+1;
        }
        if(begin<=top){
            res = Math.max(res,top-begin+1);
        }
        return res;
    }
}

思路2

public int maxConsecutive(int bottom, int top, int[] special) {
        int n = special.length;
        int[] s = new int[n+2];
        for(int i=0;i<n;i++){
            s[i] = special[i];
        }
        s[n] = bottom-1;
        s[n+1] = top+1;
        Arrays.sort(s);
        int ans = 0;
        for(int i=1;i<n+2;i++){
            ans = Math.max(ans,s[i]-s[i-1]-1);
        } 
        return ans;
    }

Problem C - 按位与结果大于零的最长组合

思路

自己没想到,统计32位每一位1的总数,哪一位的总数最大就是最长的组合。

代码

class Solution {
    public int largestCombination(int[] candidates) {
        int[] res = new int[32];
        for (int c : candidates) {
            for (int i = 0; i < 32; i++) {
                if ((c & (1 << i)) != 0) {
                    res[i]++;
                }
            }
        }
        int ret = 0;
        for(int i=0;i<32;i++){
            ret = Math.max(ret,res[i]);
        }
        return ret;
    }
}

不用辅助数组: 

public int largestCombination(int[] candidates) {
        //30位 >10^9
        int ans = 0;
        for(int i=0;i<30;i++){
            int oneCount = 0;
            for(int c:candidates){
                if((c & (1<<i)) != 0){
                    oneCount++;
                }
            }
            ans = Math.max(ans,oneCount);  //第i位的1的个数
        }
        return ans;
    }

Problem D - 统计区间中的整数数目

解法

使用

floorEntry()方法和ceilingEntry()方法相对,找到第一个小于或等于指定key的Map.Entry

想到要使用logn的查找方法去区间合并,但是没有想清楚如何合并

对JAVA的一些api的掌握不够熟练,

循环找可以合并的区间

找到小于right的第一个left然后开始合并,合并的时候修改count并且移除旧区间,

同时更新合并后的区间,最后再更新count,加入新区间

例:

第一次合并

 第二次合并

代码

class CountIntervals {
    private TreeMap<Integer,int[]> intervals;
    private int count;
    public CountIntervals() {
        //按照right排序
        intervals = new TreeMap<>();
        count = 0;
    }

    public void add(int left, int right) {
        int L = left, R=right;
        Map.Entry<Integer,int[]> tmp = intervals.floorEntry(right);
        while(tmp!=null && tmp.getValue()[1]>=L){
            L = Math.min(L,tmp.getValue()[0]);
            R = Math.max(R,tmp.getValue()[1]);
            //合并区间  减去原来的区间
            count -= (tmp.getValue()[1]-tmp.getValue()[0]+1);  //更新count
            intervals.remove(tmp.getKey());  //更新treemap
            tmp = intervals.floorEntry(right);
        }
        count += (R-L+1);
        intervals.put(L,new int[]{L,R});
    }

    public int count() {
        return  count;
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值