LeetCode第287场周赛


6055. 转化时间需要的最少操作数

题目描述

在这里插入图片描述

在这里插入图片描述

解法:贪心+模拟

算法流程:

  1. 计算出correctcurrent之间的总时间差,单位:分钟
  2. 601551从大到小的顺序计算增加的次数(借助整除运算)
class Solution {
    public int convertTime(String current, String correct) {
        if (current == null || correct == null) {
            return 0;
        }        
        int res = 0;        
        int currentHH = Integer.parseInt(current.substring(0, 2));
        int correctHH = Integer.parseInt(correct.substring(0, 2));
                
        int currentMM = Integer.parseInt(current.substring(3, 5));
        int correctMM = Integer.parseInt(correct.substring(3, 5));
        
        // 总的相差时间,单位:分
        int minutes = (correctHH - currentHH) * 60 + correctMM - currentMM;
        
        // 增加60分钟的次数
        res += (minutes / 60);
        
        minutes %= 60;        
        // 增加15分钟的次数
        res += (minutes / 15);
        
        minutes = minutes % 15;
        // 增加5分钟的次数
        res += (minutes / 5);
        
        minutes = minutes % 5;
        // 增加1分钟的次数
        res += minutes;
        
        return res;
    }
}

5235. 找出输掉零场或一场比赛的玩家

题目描述

在这里插入图片描述

在这里插入图片描述

解法:遍历+哈希表

算法流程:

  1. 定义一哈希表mapkey代表玩家,value代表输掉的次数(例如:-1代表输掉1场,-2代表输掉2场),遍历matches,利用map统计参与过比赛的玩家的输赢次数
  2. 遍历map
    • value=0,代表该玩家没有输掉任何比赛,放入answer[0]
    • value=-1,代表该玩家恰好输掉了一场比赛,放入answer[1]
  3. 按题目要求对answer[0]answer[1]进行升序排列
class Solution {
    public List<List<Integer>> findWinners(int[][] matches) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int[] match : matches) {
            map.put(match[0], map.getOrDefault(match[0], 0) );
            // 输掉比赛的次数
            map.put(match[1], map.getOrDefault(match[1], 0) - 1);
        }
        List<Integer> ans0 = new ArrayList<>();
        List<Integer> ans1 = new ArrayList<>();
        for (int person : map.keySet()) {
            if (map.get(person) == 0) {
                // 该玩家没有输掉任何比赛
                ans0.add(person);
            } else if (map.get(person) == -1) {
                // 该玩家恰好输掉了一场比赛
                ans1.add(person);
            }
        }
        // 排序
        Collections.sort(ans0);
        Collections.sort(ans1);
        List<List<Integer>> res = new ArrayList<>();
        res.add(ans0);
        res.add(ans1);
        return res;
    }
}

5219. 每个小孩最多能分到多少糖果

题目描述

在这里插入图片描述

在这里插入图片描述

二分模板题

算法流程:

  1. 计算数组candies的总和sum,若 s u m < k sum < k sum<k,直接返回0

  2. candies[i]分堆:代表 candies[i] 可以分给多个孩子

    统计当要给每个孩子分m个糖果时,计算出 candies 一共可以分够的孩子数量num,如果可以分的孩子数量num大于 k ,那么就可以增加 m 的大小

    如果这个m使用遍历的方式来寻找,那么它的范围是 0 − 1 0 7 0 - 10^7 0107,时间复杂度太高会导致超时

    所以考虑使用二分

  3. 利用二分模板,找满足每个小孩可以拿走的最大糖果数目的最后一个数

    // 找小于等于给定数的最后一个数 (满足某个条件的最后一个数)
    // 判断条件很复杂时用check函数,否则if后直接写条件即可
    boolean check(int mid) {
        // ...
        return true;
    }
    
    int binarySearch(int left, int right) {
        while (left < right) {
            int mid = left + (right - left + 1) / 2; // 右中位数
            if (check(mid)) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }
    
class Solution {
    public int maximumCandies(int[] candies, long k) {        

        if (getCandiesSum(candies) < k) {
            return 0;
        }       
        
        int left = 0, right = 10000000;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (helper(candies, mid) >= k) {
                // 若给每个孩子分配mid个糖果时,全部糖果分配的人数大于等于k,则尝试增加给每个孩子的糖果数
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        
        return left;
    }
    
    private long helper(int[] candies, int mid) {
        long res = 0;
        for (int candy : candies) {
            // 每堆糖果分成任意数量的 子堆 
            // candy / mid 代表:假设给每个孩子mid个糖果,该堆糖果可以分配给(candy/mid)个小孩
            res += (candy / mid);
        }
        // 最终返回:给每个孩子分配mid个糖果时,全部糖果一共可以分配给多少孩子
        return res;
    }
    
    private long getCandiesSum(int[] candies) {
        long res = 0;
        for (int candy : candies) {
            res += candy;
        }
        return res;
    }
    

}

5302. 加密解密字符串

题目描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

逆向思维

对于加密操作encrypt

  • 首先将keys中每个字符和其对应得索引存储在Map中,便于以O(1)复杂度找出满足keys[i]==c的下标i
  • 遍历word1中的每个字符,借助Map依次将其替换成values中的字符串

对于解密操作decrypt:

  • 逆向思考,即加密所有 dictionary \textit{dictionary} dictionary 中的字符串。用哈希表记录每个加密后的字符串的出现次数。这样每次调用 decrypt 时,返回哈希表中 word 2 \textit{word}_2 word2 的出现次数即可
  • Note: 加密 dictionary \textit{dictionary} dictionary 各个字符串的过程中,需要判断字符是否在 keys \textit{keys} keys
class Encrypter {

    private String[] values;

    private Map<Character, Integer> keysMap;

    private Map<String, Integer> cnt;

    public Encrypter(char[] keys, String[] values, String[] dictionary) {
        this.values = values;
        this.keysMap = new HashMap<>();
        this.cnt = new HashMap<>();
        for (int i = 0; i < keys.length; i++) {
            keysMap.put(keys[i], i);
        }
        for (String s : dictionary) {
            String e = encrypt(s);
            cnt.put(e, cnt.getOrDefault(e, 0) + 1);
        }
    }

    public String encrypt(String word1) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < word1.length(); i++) {
            if (!keysMap.containsKey(word1.charAt(i))) {
                return "";
            }
            int idx = keysMap.get(word1.charAt(i));            
            sb.append(values[idx]);
        }
        return sb.toString();
    }

    public int decrypt(String word2) {
        return cnt.getOrDefault(word2, 0);
    }
}

/**
 * Your Encrypter object will be instantiated and called as such:
 * Encrypter obj = new Encrypter(keys, values, dictionary);
 * String param_1 = obj.encrypt(word1);
 * int param_2 = obj.decrypt(word2);
 */

Reference

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xylitolz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值