1154. Day of the Year
给定一个字符串日期,返回该天是该年的第几天
首先把字符串按年月日拎出来,判断是否为闰年,最后求和即可
class Solution {
public:
int strtoInt(string s)
{
int begin = 0;
for (int i = 0; i < s.length(); ++i)
if (s[i] == '0') begin++;
else break;
int res = 0;
for (int i = begin; i < s.length(); ++i)
res = res * 10 + s[i] - '0';
return res;
}
int dayOfYear(string date) {
int year = strtoInt(date.substr(0, 4));
int month = strtoInt(date.substr(5, 2));
int day = strtoInt(date.substr(8));
int ds[12] = { 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int res = day;
for (int i = 0; i < month - 1; ++i)
res += ds[i];
if (month > 2)
{
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
res -= 1;
else res -= 2;
}
return res;
}
};
1155. Number of Dice Rolls With Target Sum
给定d个骰子,每个骰子有f个面,编号从1~f,抛d次,使得和为target,共有多少种情况,对所有的方案数取模(1e9+7)
明显的dp,dp[i][j]表示用i个骰子抛出和为j的情况数,因此
代码如下:
const int MOD = 1000000007;
class Solution {
public:
int numRollsToTarget(int d, int f, int target)
{
if (target == d * f) return 1;
if (target > d * f) return 0;
vector<vector<int>> dp(d + 1, vector<int>(d * f + 1, 0));
for(int i = 1; i <= f; ++i)
dp[1][i] = 1;
for (int i = 2; i <= d; ++i)
{
int minn = i - 1, maxn = (i - 1) * f;
for (int j = maxn; j >= minn; --j)
{
for (int k = f; k > 0; --k)
dp[i][j + k] = (dp[i][j + k] + dp[i - 1][j]) % MOD;
}
}
return dp[d][target];
}
};
1156. Swap For Longest Repeated Character Substring
给定一个字符串,仅能交换一次,判断最多有多少个连续的重复字符
从头遍历,直到找到第二个不同字符(因为只能交换一次)此轮结束:
class Solution {
public:
int maxRepOpt1(string text) {
map<char, int> count;
for (char c : text)
count[c]++;
int maxn = 1;
for (int i = 0; i < text.length(); ++i)
{
if (count[text[i]] < 2) continue;
int cnt = 1, cur = 1;
for (int j = i + 1; j < text.length(); ++j)
{
if (text[j] != text[i])
{
if (cnt == 0) break;
else cnt--, cur++;
}
else cur++;
}
cur = min(cur, count[text[i]]);
maxn = max(maxn, cur);
}
return maxn;
}
};
1157. Online Majority Element In Subarray
首先根据给定数组初始化,之后每个Query包含三个数:left、right和threshold,返回在[left, right]下标的区间内,出现次数超过threshold的数字,若不存在,则返回-1
很明显不能每次query都遍历一遍记录出现次数,会TLE,因此在初始化时需要做一些预先操作,我这里保存了三个数:
prepos: 表示数组中每个数出现的位置
presum: presum[i]表示到下标i为止,出现次数最多的数的个数
precnt: 内存放的是一个pair<int, int>,表示每个数字(first)出现的个数(second)
cmp表示将precnt按照出现次数从高到低排序
因此,每次query时,先判断到presum[right]为止,出现最多的次数,是否超过threshold,若比threshold小,则直接返回-1
之后,从头遍历precnt,以及用lower_bound()函数(本质是二分),从prepos中找到其在[left, right]区间内最早和最晚出现的位置,两个位置之间的距离若大于等于threshold,则找到,否则一直寻找,直至找不到返回-1
class MajorityChecker {
private:
vector<int> v;
unordered_map<int, vector<int>> prepos;
vector<int> presum;
vector<pair<int, int>> precnt;;
public:
static bool cmp(const pair<int, int>& p1, const pair<int, int>& p2)
{
return p1.second > p2.second;
}
MajorityChecker(vector<int>& arr) {
v = arr;
presum.resize(arr.size(), 0);
precnt.resize(20001);
for(int i = 0; i < arr.size(); ++i)
{
pair<int, int> p = precnt[arr[i]];
precnt[arr[i]] = make_pair(arr[i], p.second + 1);
prepos[arr[i]].emplace_back(i);
if(i == 0) presum[i] = precnt[arr[i]].second;
else presum[i] = max(presum[i - 1], precnt[arr[i]].second);
}
sort(precnt.begin(), precnt.end(), cmp);
}
int query(int left, int right, int threshold) {
if(presum[right] < threshold) return -1;
int maxn = 0;
for(int i = 0; i < precnt.size(); ++i)
{
if(precnt[i].second < threshold) break;
int num = precnt[i].first;
vector<int>::iterator it1 = lower_bound(prepos[num].begin(), prepos[num].end(), left),
it2 = lower_bound(prepos[num].begin(), prepos[num].end(), right);
if(v[right] != num) it2--;
if(it2 - it1 + 1 >= threshold) return num;
}
return -1;
}
};
/**
* Your MajorityChecker object will be instantiated and called as such:
* MajorityChecker* obj = new MajorityChecker(arr);
* int param_1 = obj->query(left,right,threshold);
*/