2022-03-01每日刷题打卡

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个数,每个数都是01表示能否走到,数字之间不用空格隔开。

输入样例

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值