- 本人的LeetCode账号:魔术师的徒弟,欢迎关注获取每日一题题解,快来一起刷题呀~
- 本人Gitee账号:路由器,欢迎关注获取博客内容源码。
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)
{
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)
{
LL l = 0, r = accumulate(time.begin(), time.end(), (LL)0);
while (l < r)
{
LL mid = (l + r) >> 1;
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];
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.扯淡
??函数类二分不熟悉。。。哎,手速也太慢了,上分真是困难啊,不过还好这周没掉分,多练练函数类二分希望下次遇到能快速想到并写出来吧。
|