929. 独特的电子邮件地址 / 剑指 Offer II 073. 狒狒吃香蕉

929. 独特的电子邮件地址【简单题】【每日一题】

思路:【哈希模拟】

遍历emails数组,对每个邮箱email@进行切分,左侧为local,右侧为domain,对local进行进一步处理。
如果local包含+,则将自+往右的字符全部截掉;然后从左到右遍历新的local,将.去掉,最后将localdomain拼接起来尝试存入哈希集合set中,如果添加成功,则计数变量cnt自增1
当所有的邮箱处理完之后,返回cnt即可。

代码:

class Solution {
    public int numUniqueEmails(String[] emails) {
        int cnt = 0;
        Set<String> set = new HashSet<>();
        for (String email : emails) {
            int split = email.indexOf('@');
            String domain = email.substring(split);
            String local = email.substring(0,split);
            if (local.contains("+")){
                int idx = local.indexOf('+');
                local = local.substring(0,idx);
            }
            StringBuilder sb = new StringBuilder();
            for (char c : local.toCharArray()) {
                if (c != '.'){
                    sb.append(c);
                }
            }
            local = sb.toString();
            if (set.add(local+domain)){
                cnt++;
            }
        }
        return cnt;
    }
}

剑指 Offer II 073. 狒狒吃香蕉【中等题】

思路:【二分查找】

我们模拟一遍这个狒狒吃香蕉的过程,设速度为k
遍历这n堆香蕉,
如果香蕉堆里的香蕉小于等于k,那么吃掉这堆香蕉需要用1小时,我们假设距警卫回来还有remain小时(remain初始值为警卫的离开时间h),那么remain--
如果香蕉堆里的香蕉大于k,那么吃掉这堆香蕉消耗的时间为i/k,结果向上取整,将花费的时间在remain中减掉。
遍历完之后判断remain0的大小关系,
如果remain>0,说明香蕉吃完了,警卫还没回来;
如果remain==0,说明刚好香蕉吃完,警卫回来;
如果remain<0,说明香蕉还没吃完,警卫就回来了。

我们可以通过二分查找的方式来求出使remain==0k的最小值。
根据题意,狒狒吃香蕉的速度k最小取1,最大取香蕉堆中的最大值(因为警卫离开的时间至少为n)
于是,令left = 1,right = max(max为香蕉堆的最大值)。
left<=right时,进入while循环,令kleftright的中间值,对当前的k值进行上述狒狒吃香蕉的模拟。
remain >= 0时,说明k值大了,香蕉吃完了,警卫还没回来,此时考虑缩小k,更新右区间;
remain < 0时,说明k值小了,香蕉还没吃完,警卫就回来了,此时考虑扩大k,更新左区间。

当二分查找结束时,left值即为我们要找的满足remain == 0 的最小值。

代码:

class Solution {
    public int minEatingSpeed(int[] piles, int h) {
        int right = 0;
        for (int pile : piles) {
            if (pile > right){
                right = pile;
            }
        }
        int left = 1;
        int remain = h;
        while (left <= right){
            int k = left + ((right-left)>>1);
            for (int i : piles) {
                if (i <= k){
                    remain--;
                }else {
                    remain -= i / k;
                    if (i % k != 0){
                        remain--;
                    }
                }
            }
            //remain >= 0 说明 k 值大了 香蕉吃完了 警卫还没回来
            if (remain >= 0){
                //更新右区间
                right = k - 1;
            }else {//remain < 0 说明 k 值小了 香蕉还没吃完 警卫就回来了
                //更新左区间
                left = k + 1;
            }
            //remain重置为 h 用新的k值重新模拟
            remain = h;
        }
        return left;
    }
}

你可能感兴趣的:(力扣刷题记录,算法,leetcode,java,刷题记录)