2022-03-01每日刷题打卡
力扣——每日一题
6. Z 字形变换
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”
class Solution {
public:
string convert(string s, int numRows) {
if(numRows==1)return s;
vector<string>v(numRows);
int ans=1,l=0;
for(auto i:s)
{
v[l].push_back(i);
if(l+ans>=numRows)ans=-1;
else if(l+ans<0)ans=1;
l+=ans;
}
string str;
for(auto i:v)
{
for(auto j:i)
str+=j;
}
return str;
}
};
代码源——Div2每日一题
简单分数统计 - 题目 - Daimayuan Online Judge
N 个好朋友在codeforces上参加一场包含 M 个题目的比赛, 比赛期间codeforces网站一共有 k 次提交。
已知每个题目的分数,
但是由于他们只能查到在比赛期间codeforces总共的提交记录(其他用户提交的其他题目记录也包含在内, 即存在不属于该场比赛的题目),
所以想请你编写一个程序算出他们每个人的分数。
输入格式
第一行三个整数 N, M, K 分别表示好朋友的个数, 题目的个数, 和提交的总次数(其中0<N,M,K<=200)。
接下来 N 行 第 i 行输入为第 i 个人的id,
接下来 M 行 第 j 行输入为第 j 个题目的名称和分数,
接下来K行 第 k 行输入为第 k 次提交的提交者id, 题目名称和结果(“WA” 或 “AC”, 如果"AC"代表通过这个题目, 提交者获得对应分数)。
注: 题目名称和id均为仅包含英文字母和数字的字符串, 题目分数为小于等于 1e6 的正整数. 每一行的多个输入之间用空格隔开。
所有输入的字符串长度 length 满足 0<length≤500。
所有用户id和题目名称不存在重名, 且同一个人重复AC不会增加分数, 好朋友们只会提交属于比赛的题目。
输出格式
输出 N 行, 第 i 行输出第 i 个人的名字和对应分数 (名字和分数用空格隔开)。
样例输入
2 2 4
GabrielPessoa
beza
metebronca 100
geometry 200
beza metebronca AC
ffern numbertheory AC
GabrielPessoa geometry WA
beza geometry AC
样例输出
GabrielPessoa 0
beza 300
样例解释
beza 过了 metebronca和geometry 拿到 300 分
GabrielPessos 没有过题, 所以是 0 分
还有一些其他选手提交的其他题目忽略不计
额,就很正常的模拟就行。难度等同cf800分:)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<stack>
typedef long long ll;
const int N = 550;
int main()
{
map<string, map<string, int>>people;
map<string, int>score;
int n, m, k;
cin >> n >> m >> k;
vector<string>names(n);
for (int i = 0; i < n; i++)
cin >> names[i];
for (int i = 0; i < m; i++)
{
int num;
string str;
cin >> str >> num;
score[str] = num;
}
for (int i = 0; i < k; i++)
{
string name,pro,flag;
cin >> name >> pro >> flag;
if (flag == "AC")
people[name][pro] = score[pro];
}
for (int i = 0; i < n; i++)
{
ll sum = 0;
for (auto j : people[names[i]])
sum += j.second;
cout << names[i] << " " << sum << endl;
}
return 0;
}
走路 - 题目 - Daimayuan Online Judge
有一条很长的数轴,一开始你在0的位置。接下来你要走n步,第i步你可以往右走ai或者bi。
问n步之后,0到m的每个位置,能不能走到?
输入格式
第一行,两个整数n,m。
接下来n行,每行两个整数ai,bi。
输出格式
一行,一共m+1个数,每个数都是0
或1
表示能否走到,数字之间不用空格隔开。
输入样例
3 10
1 2
2 6
3 3
输出样例
00000011001
数据规模
对于所有数据,保证1≤n≤100,1≤m≤105,1≤ai,bi≤1000。
这题昨天愣是不知道啥意思,想着如果是记录走过的点,那1 2 3 4 5 6 7 8 10位置上应该都是1才对,今天才知道,是看你走完n步后到达哪个位置。过程走的不算,这样就是6 7 10了。这题就相当于让你用给的这些数组合加一起,看能得出多少不同结果。
用一个二维数组f来求,f[i] [j]的定义是:走了i步后,在第j个位置上,如果到达了这个位置,f[i] [j]=1,反之为0。状态转移:每走一步i+1,然后先判断f[i] [j]是否等于1,如果等于1就计算j+a[i]是否小于等于m(不能超出范围),满足,则f[i+1] [j+a[i]]=1,反之为0。对b[i]也进行如上操作。
因为我们要的是走了n步后的情况,那我们就遍历f[n] [j]这一层,如果f[n] [j]==1,说明到达了这里,输出1,反之输出0.
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<stack>
typedef long long ll;
const int N = 100005;
ll f[550][N], a[150], b[150];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> a[i] >> b[i];
f[0][0] = 1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j <= m; j++)
{
if (f[i][j] == 1 && f[i + 1][j + a[i]] <= m)
f[i + 1][j + a[i]] = 1;
if (f[i][j] == 1 && f[i + 1][j + b[i]] <= m)
f[i + 1][j + b[i]] = 1;
}
}
for (int i = 0; i <= m; i++)
if (f[n][i] == 1)cout << 1;
else cout << 0;
return 0;
}
力扣
2185. 统计包含给定前缀的字符串
给你一个字符串数组 words 和一个字符串 pref 。
返回 words 中以 pref 作为 前缀 的字符串的数目。
字符串 s 的 前缀 就是 s 的任一前导连续字符串。
示例 1:
输入:words = [“pay”,“attention”,“practice”,“attend”], pref = “at”
输出:2
解释:以 “at” 作为前缀的字符串有两个,分别是:“attention” 和 “attend” 。
遍历words的每个元素,如果元素长度小于pref长度就跳过(都比它短了怎么可能前缀会是pref),在长度大于pref的元素里找,每次取字符串的前缀,看是否等于pref,不等于就去找下一个,等于则计数器++。最后返回计数器。
class Solution {
public:
int prefixCount(vector<string>& words, string pref) {
int n=words.size(),m=pref.size(),res=0;
for(int i=0;i<n;i++)
{
if(words[i].size()<m)continue;
string str;
for(int j=0;j<m;j++)str+=words[i][j];
if(str==pref)res++;
}
return res;
}
};
2186. 使两字符串互为字母异位词的最少步骤数
给你两个字符串 s 和 t 。在一步操作中,你可以给 s 或者 t 追加 任一字符 。
返回使 s 和 t 互为 字母异位词 所需的最少步骤数。
字母异位词 指字母相同但是顺序不同(或者相同)的字符串。
示例 1:
输入:s = “leetcode”, t = “coats”
输出:7
解释:
- 执行 2 步操作,将 “as” 追加到 s = “leetcode” 中,得到 s = “leetcodeas” 。
- 执行 5 步操作,将 “leede” 追加到 t = “coats” 中,得到 t = “coatsleede” 。
“leetcodeas” 和 “coatsleede” 互为字母异位词。
总共用去 2 + 5 = 7 步。
可以证明,无法用少于 7 步操作使这两个字符串互为字母异位词。
两个哈希表存两个字符串的组成情况,然后计算它们字符出现的差值的绝对值即可。
class Solution {
public:
int word[26];
int minSteps(string s, string t) {
map<char,int>map_s1,map_t1;
for(auto i:s)map_s1[i]++,word[i-'a']=1;
for(auto i:t)map_t1[i]++,word[i-'a']=1;
int res=0;
for(int i=0;i<26;i++)
{
if(word[i]==1)
{
char a=i+'a';
res+=abs(map_t1[a]-map_s1[a]);
}
}
return res;
}
};
2187. 完成旅途的最少时间
给你一个数组 time ,其中 time[i] 表示第 i 辆公交车完成 一趟旅途 所需要花费的时间。
每辆公交车可以 连续 完成多趟旅途,也就是说,一辆公交车当前旅途完成后,可以 立马开始 下一趟旅途。每辆公交车 独立 运行,也就是说可以同时有多辆公交车在运行且互不影响。
给你一个整数 totalTrips ,表示所有公交车 总共 需要完成的旅途数目。请你返回完成 至少 totalTrips 趟旅途需要花费的 最少 时间。
示例 1:
输入:time = [1,2,3], totalTrips = 5
输出:3
解释:
- 时刻 t = 1 ,每辆公交车完成的旅途数分别为 [1,0,0] 。
已完成的总旅途数为 1 + 0 + 0 = 1 。 - 时刻 t = 2 ,每辆公交车完成的旅途数分别为 [2,1,0] 。
已完成的总旅途数为 2 + 1 + 0 = 3 。 - 时刻 t = 3 ,每辆公交车完成的旅途数分别为 [3,1,1] 。
已完成的总旅途数为 3 + 1 + 1 = 5 。
所以总共完成至少 5 趟旅途的最少时间为 3 。
这题我万万没想到做法居然是二分(“见最少或最大满足,本能反应就是二分”——群里大佬如是说)。
我们完成旅途所需的最多时间应该是取时间最少的那一趟旅途,走它个totalTrips次(别问为什么最多时间不是选时间最长那一趟走totalTrips次,有脑子都不会这么选),这样时间最长是totalTrips*那一趟旅途所需时间。我们可以先把time数组升序排序,二分差值左区间是0,右区间是最长时间totalTrips *time[0]。开始二分,每次取中间mid,然后用一个计数器记录这个时间所能走的旅途数的总和,每趟旅途能走的次数是mid/time[i],当time[i]>mid时结束记录,然后我们比较旅途数的总和和totalTrips的关系,如果大于等于,说明这时间还能压,我们在左边找答案,如果不够totalTrips,说明时间不够,我们在右区间找答案。
class Solution {
public:
long long minimumTime(vector<int>& time, int totalTrips) {
sort(time.begin(),time.end());
long long left=0,right=1L*time[0]*totalTrips;
while(left<right)
{
long long mid=(left+right)/2,res=0;
for(auto i:time)
{
if(i>mid)break;
res+=mid/i;
}
if(res>=totalTrips)right=mid;
else left=mid+1;
}
return left;
}
};