IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode第287场周赛前四题题解(函数类二分的练习) -> 正文阅读

[数据结构与算法]LeetCode第287场周赛前四题题解(函数类二分的练习)

- 本人的LeetCode账号:魔术师的徒弟,欢迎关注获取每日一题题解,快来一起刷题呀~

1 转化时间需要的最小时间数

??思路比较简单,模拟即可,考虑到如果correct的分钟数小于current的分钟数,则只增加correct - current - 1个小时数,然后让correct的分钟数+60,然后再算current的分钟数变到correct的分钟数需要的时间;如果correcct的分钟数大于等于current的分钟数,则增加correct - current个小时数,然后计算current的分钟数边到correct的分钟数用的时间即可。

class Solution {
public:
    int convertTime(string current, string correct) 
    {
        int res = 0;
        int hour1 = stoi(current.substr(0, 2));
        int hour2 = stoi(correct.substr(0, 2));
        int min1 = stoi(current.substr(3, 2));
        int min2 = stoi(correct.substr(3, 2));
        if (min2 < min1)
        {
            res += hour2 - hour1 - 1;
            min2 += 60;
        }
        else 
        {
            res += hour2 - hour1;
        }    
        int gap = min2 - min1;
        res += gap / 15;
        gap %= 15;
        res += gap / 5;
        gap %= 5;
        res += gap;
        return res;
    }
};

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

??本题的思路也很简单,用一个哈希表统计选手失败的次数,如果是胜者,则myhash[winner];,表示只是插入winner,其失败次数为0,为了保证有序,我们可以用一个map<int, int>来存储,第一个键值表示号,第二个键值表示失败次数,最后遍历一遍哈希表即可。

class Solution {
public:
    vector<vector<int>> findWinners(vector<vector<int>>& matches) 
    {
        map<int, int> myhash;
        for (const auto& match : matches)
        {
            myhash[match[0]];
            myhash[match[1]]++;
        }
        vector<vector<int>> ans(2);
        for (auto p : myhash)
        {
            if (p.second == 0)
            {
                ans[0].push_back(p.first);
            }
            else if (p.second == 1)
            {
                ans[1].push_back(p.first);
            }
        }
        return ans;    
    }
};

??反思:其实我比赛思路是用unordered_map + set去重,不过写起来比较长,延误了一些时间。

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

??本题是比较典型的函数类二分题目,随着每个小孩能够分到的糖果树的增加,它所映射到的能够分给的小孩数会单调减少,所以会把每个小孩分到的糖果数分成两个区间,左边区间是能够分给的小孩数大于k,右边区间是能够分给的小孩书小于等于k,所以我们可以找能够分给的小孩数量>=k这一区间的右端点,用二分就可以做到,注意题目条件,每个小孩最多拿走一堆糖果,即二分的有边界是*max_element(candies.begin(), candies.end())

class Solution {
public:
    typedef long long LL;
    int maximumCandies(vector<int>& candies, long long k) 
    {
        LL sum = accumulate(candies.begin(), candies.end(), LL(0));
        if (sum < k) return 0;
        if (sum == k) return 1;
        int l = 0, r = *max_element(candies.begin(), candies.end());
        while (l < r)
        {
            int mid = (l + r + 1) >> 1;
            LL cnt = 0;
            for (int c : candies)
            {
                cnt += c / mid;
            }
            if (cnt >= k)
            {
                l = mid;
            }
            else 
            {
                r = mid - 1;
            }
        }
        return r;
    }
};

??反思:考场上这个题做的很慢,因为函数类二分不太熟悉,而且这题必须得用左区间的右端点,因为右区间的左端点可能不是最大的糖果数,可能是满足给分k个小孩的最小糖果数,我们要找的是够分k个小孩的最大糖果数,所以是左区间的右端点。

相似题目练习

class Solution {
public:
    int minimumSize(vector<int>& nums, int maxOperations) 
    {
        // 单个袋子中的球的数目的最大值为y
        // 很容易发现y增加,操作次数减少
        // 我们要找操作次数小于等于maxOperations的最小的y
        // 即右区间 op(y) <= maxOperations的左端点
        // 操作次数的获得公式是 ∑ (nums[i] - 1) / y 对i求和
        // y的左端点是1 右端点是max_element(nums)
        int l = 1, r = *max_element(nums.begin(), nums.end());
        while (l < r)
        {
            int mid = (l + r) >> 1;
            int op = 0;
            for (auto p : nums)
            {
                op += (p - 1) / mid;
            }
            if (op <= maxOperations) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};
class Solution {
public:
    typedef long long LL;
    int minTime(vector<int>& time, int m) 
    {
        // 做题用时最多的一天用时为T 显然随着T的增加 所用天数m会单调减少
        // 所以这是一个可以用二分解决的问题
        // 最大的痛点在于如何同T得到m 因为这里头有小杨的帮助
        // 因为要求最小的T 可以用贪心策略 不管怎么样先让小杨帮我
        // 然后后续再及时维护用时最长的work
        LL l = 0, r = accumulate(time.begin(), time.end(), (LL)0);
        while (l < r)
        {
            LL mid = (l + r) >> 1;
            // 这个check函数是表示最多一天用时mid 能够在m天内完成
            // 我们找能够早m天内完成的区间的左端点
            if (check(mid, time, m) == true)
            {
                r = mid;
            }
            else l = mid + 1;
        }
        return l;
    }
    bool check(LL limit, const vector<int>& time, int m)
    {
        LL cursum = 0;
        int curmax = time[0];
        // 先把第0天的题找小杨帮上 后续再通过max min来换成这段时间用时最长的题让小杨帮
        int useddays = 1;// 当前是第几天
        for (int i = 1; i < time.size(); ++i)
        {
            int t = time[i];
            // 如果今天还能再做
            if (cursum + min(curmax, t) <= limit)
            {
                cursum += min(curmax, t);
                curmax = max(curmax, t);
            }
            
            // 否则只能到下一天了
            else
            {
                cursum = 0;// 继续让第一题就然小杨帮
                curmax = t;// 当前题就是明天第一题
                useddays++;
            }
        }
        return useddays <= m;
    }
};

4 加密解密字符串

??对于加密部分,我们考虑用一个哈希表,由keys映射到values,这样就能够完成加密。

??对于解密部分,我们可以先把词典中所有允许为答案的字符串全部通过加密函数得到它们加密后的串,然后用一个哈希表统计它们能变化来的加密后的串的数量,解密时直接返回这个数量即可。

class Encrypter {
public:
    Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) 
    {
        for (int i = 0; i < keys.size(); ++i)
        {
            keytoval[keys[i]] = values[i];
        }
        for (string& wd : dictionary)
        {
            ++cnt[encrypt(wd)];
        }
    }
    
    string encrypt(string word1) 
    {
        string res;
        for (char ch : word1)
        {
            res += keytoval[ch];
        }
        return res;
    }
    
    int decrypt(string word2) 
    {
        if (!cnt.count(word2)) return 0;
        return cnt[word2];
    }
private:
    unordered_map<char, string> keytoval;
    unordered_map<string, int> cnt;
};

??脑筋急转弯不会转,字典树不会调,入土了。

5.扯淡

??函数类二分不熟悉。。。哎,手速也太慢了,上分真是困难啊,不过还好这周没掉分,多练练函数类二分希望下次遇到能快速想到并写出来吧。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:36:03  更:2022-04-04 12:36:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:02:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码