第一题:链接:https://www.nowcoder.com/questionTerminal/824af5cb05794606b56657bb3fa91f49
编程题]善变的同伴
- 热度指数:601 时间限制:1秒 空间限制:65536K
- 算法知识视频讲解
又到了吃午饭的时间,你和你的同伴刚刚研发出了最新的GSS-483型自动打饭机器人,现在你们正在对机器人进行功能测试。
为了简化问题,我们假设午饭一共有N个菜,对于第i个菜,你和你的同伴对其定义了一个好吃程度(或难吃程度,如果是负数的话……)A[i],
由于一些技(经)术(费)限制,机器人一次只能接受一个指令:两个数L, R——表示机器人将会去打第L~R一共R-L+1个菜。
本着不浪费的原则,你们决定机器人打上来的菜,含着泪也要都吃完,于是你们希望机器人打的菜的好吃程度之和最大
然而,你善变的同伴希望对机器人进行多次测试(实际上可能是为了多吃到好吃的菜),他想知道机器人打M次菜能达到的最大的好吃程度之和
当然,打过一次的菜是不能再打的,而且你也可以对机器人输入-1, -1,表示一个菜也不打
输入描述:
第一行:N, M
第二行:A[1], A[2], ..., A[N]
输出描述:
一个数字S,表示M次打菜的最大好吃程度之和
示例1
输入
7 2
1 2 3 -2 3 -10 3
输出
10
说明
[1 2 3 -2 3] -10 [3]
示例2
输入
7 4
1 2 3 -2 3 -10 3
输出
12
说明
[1 2 3] -2 [3] -10 [3]
第四次给机器人-1, -1的指令
备注:
N <= 10^5 = 100000
|A[i]| <= 10^4 = 10000
10%数据M = 1
50%数据M <= 2
80%数据M <= 100
100%数据M <= 10^4 = 10000
解题思路:最大m子段合,可以参考https://blog.csdn.net/winter2121/article/details/72848482
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
vector<int>ss;
int dp[2][100005]={0};
int main()
{
int N, M,sum,h, k, count, now; //N表示菜的个数,M表示机器人最多打菜的次数,cout表示菜的总的好吃度,now表示当前这道菜的好吃度
cin >> N >> M;
count = 0;
while (N--) {
cin >> now; //输入菜的好吃程度
if (count>0) { //总的好吃度为正时
if (now >= 0) //好吃度为正,累加好吃度
count += now;
else {
ss.push_back(count); //好吃度为负,把之前总的好吃度存下来,并更新总的好吃度
count = now;
}
}
else if (count<0) { //总的好吃度为负数时
if (now >= 0) {
ss.push_back(count); //当前好吃度为正,把之前总的好吃度存下来,并更新总的好吃度
count = now;
}
else
count += now; //好吃度为负,累加好吃度
}
else
count += now; //总的好吃度为0时,累加好吃度
}
if (count>0) //完成数据输入后,总的好吃度如果为正,那么存下来
{
ss.push_back(count);
}
sum = 0;
N = ss.size()+1;
count = 0;
//可操作次数大于存储下来的总好吃值个数,直接把正的都取出来累加就是最终的总的好吃度
if(N<=M){
for (int j = 0; j < N; j++){
if(ss[j]>0)
count+=ss[j];
}
return 0;
}
//可操作次数小于存储下来的总的好吃值的个数,转换为二维dp
else{
for (int i = 1; i <= M; i++) {
sum = 0;
k=i&1;
h=(i-1)&1;
//dp[k][0] = 0;
for (int j = 1; j < N; j++) {
sum = max(sum, dp[h][j - 1]);
dp[k][j] = max(sum , dp[k][j - 1]) + ss[j-1];
}
}
for(int i=M;i<N;i++)
if (count < dp[k][i])
count = dp[k][i];
}
cout << count << endl;
return 0;
}
第二题:
题目描述
通过键盘输入一串小写字母(a~z)组成的字符串。
请编写一个字符串归一化程序,统计字符串中相同字符出现的次数,并按字典序输出字符及其出现次数。
例如字符串"babcc"归一化后为"a1b2c2"
输入描述:
每个测试用例每行为一个字符串,以'\n'结尾,例如cccddecca
输出描述:
输出压缩后的字符串ac5d2e
示例1
输入
dabcab
输出
a2b2c1d1
解题思路:直接使用map存储即可,可以不用排序。
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int main()
{
int n,m;
string str;
cin>>str;
map<char,int> letter;
for(int i=0;i<str.size();i++){
char temp=str[i];
// if(letter.find(temp)){
letter[str[i]]++;
// }
// else letter[str[i]]=1;
}
map<char,int>::iterator it;
it=letter.begin();
for(it;it!=letter.end();it++){
cout<<it->first<<it->second;
}
}
题目描述
月神拿到一个新的数据集,其中每个样本都是一个字符串(长度小于100),样本的的后六位是纯数字,月神需要将所有样本的后六位数字提出来,转换成数字,并排序输出。
月神要实现这样一个很简单的功能确没有时间,作为好朋友的你,一定能解决月神的烦恼,对吧。
输入描述:
每个测试用例的第一行是一个正整数M(1<=M<=100),表示数据集的样本数目
接下来输入M行,每行是数据集的一个样本,每个样本均是字符串,且后六位是数字字符。
输出描述:
对每个数据集,输出所有样本的后六位构成的数字排序后的结果(每行输出一个样本的结果)
示例1
输入
4
abc123455
boyxx213456
cba312456
cdwxa654321
输出
123455
213456
312456
654321
解题思路:看到需要排序,想到用set存储,然后把后六位存储即可。
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int main()
{
int n,m;
string str;
cin>>n;
set<string> letter;
for(int i=0;i<n;i++){
cin>>str;
string temp;
for(int j=str.size()-6;j<str.size();j++){
temp+=str[j];
}
letter.insert(temp);
}
set<string>::iterator it;
it=letter.begin();
for(it;it!=letter.end();it++){
cout<<*it<<endl;
}
}
/*
3 3
1 100
10 1000
1000000000 1001
9 10 1000000000
*/
第三题:
题目描述
最大回文子串是被研究得比较多的一个经典问题。最近月神想到了一个变种,对于一个字符串,如果不要求子串连续,那么一个字符串的最大回文子串的最大长度是多少呢。
输入描述:
每个测试用例输入一行字符串(由数字0-9,字母a-z、A-Z构成),字条串长度大于0且不大于1000.
输出描述:
输出该字符串的最长回文子串的长度。(不要求输出最长回文串,并且子串不要求连续)
示例1
输入
adbca
输出
3
解题思路:最长回文子序列
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int dp[2][1500];
int main()
{
string str;
cin>>str;
int len = str.length();
memset(dp,0,sizeof(dp));
int cur = 0;
for(int i = len - 1; i >= 0; i--)
{
cur ^= 1;
dp[cur][i] = 1;
for(int j = i + 1; j < len; j++)
{
if(str[i] == str[j])
dp[cur][j] = dp[cur^1][j-1] + 2;
else
dp[cur][j] = max(dp[cur][j-1],dp[cur^1][j]);
}
}
cout<<dp[cur][len-1];
}
题目描述
有重量分别为3,5,7公斤的三种货物,和一个载重量为X公斤的箱子(不考虑体积等其它因素,只计算重量)
需要向箱子内装满X公斤的货物,要求使用的货物个数尽可能少(三种货物数量无限)
输入描述:
输入箱子载重量X(1 <= X <= 10000),一个整数。
输出描述:
如果无法装满,输出 -1。
如果可以装满,输出使用货物的总个数。
解题思路:多重揹包问题
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int dp[4][10003]={100000};
int main()
{
int n;
cin>>n;
int b[4]={0,3,5,7};
for(int j=0;j<=3;j++){
for(int i=0;i<=n;i++){
dp[j][i]=1000000;
}
}
dp[0][0]=0;
for(int j=1;j<=3;j++){
dp[j][0]=0;
for(int i=1;i<=n;i++){
dp[j][i]=dp[j-1][i];
}
for(int i=1;i<=n;i++){
int k=1;
while((i-k*b[j])>=0){
dp[j][i]=min(dp[j-1][i-k*b[j]]+k,dp[j][i]);
k++;
}
// cout<<dp[j][i]<<' ';
}
// cout<<endl;
}
if(dp[3][n]==1000000) cout<<-1;
else cout<<dp[3][n];
}
题目描述
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
("回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。)
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。
可用C++,Java,C#实现相关代码逻辑
输入描述:
输入一个字符串S 例如“aabcb”(1 <= |S| <= 50), |S|表示字符串S的长度。
输出描述:
符合条件的字符串有"a","a","aa","b","c","b","bcb"
所以答案:7
解题思路:以每一个字符为中间点向两侧扩散,扩散成功则加1,失败则换下一个点
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int main()
{
string str;
cin>>str;
int count=str.size();
for(int i=0;i<str.size()-1;i++){
if(str[i+1]==str[i-1]){
count++;
// cout<<1<<endl;
for(int j=2;j<str.size()-i+1&&j<=i;j++){
if(str[i+j]==str[i-j]){
count++;
}
else{
break;
}
}
}
if(str[i]==str[i+1]){
count++;
// cout<<2<<endl;
for(int j=1;j<str.size()-i&&j<=i;j++){
// cout<<i<<' '<<j<<endl;
if(str[i+j+1]==str[i-j]){
// cout<<3<<endl;
count++;
}
else{
break;
}
}
}
}
cout<<count;
}
题目描述
一个非空整数数组,选择其中的两个位置,使得两个位置之间的数和最大。
如果最大的和为正数,则输出这个数;如果最大的和为负数或0,则输出0
解题思路:累加,小于零就放弃,重新开始,每次累加与最大值比较。
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int main(){
int a[100000];
int length=0;
for(int i=0;;i++)
{
scanf("%d",&a[i]);
length ++;
if(getchar()=='\n')
break;
}
vector<int> b;
int count=a[0];
for(int i=1;i<length;i++){
if(a[i]<0){
if(count<=0) count+=a[i];
else{
b.push_back(count);
count=a[i];
}
}
else{
if(count>=0) count+=a[i];
else{
b.push_back(count);
count=a[i];
}
}
}
b.push_back(count);
int max=0;
count=0;
for(int i=0;i<b.size();i++){
count+=b[i];
// cout<<count<<endl;
if(max<count) max=count;
if(count<0) count=0;
}
cout<<max;
return 0;
}
/*
3 -5 7 -6 5
*/
题目描述
已知一个字符串数组words,要求寻找其中两个没有重复字符的字符串,使得这两个字符串的长度乘积最大,输出这个最大的乘积。如:
words=["abcd","wxyh","defgh"], 其中不包含重复字符的两个字符串是"abcd"和"wxyh",则输出16
words=["a","aa","aaa","aaaa"], 找不到满足要求的两个字符串,则输出0
解题思路:把输入处理好就可以暴力破解了。
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<set>
#include<map>
using namespace std;
int main(){
string str;
vector<string> s;
getline(cin,str);
string temp;
for(int i=0;i<str.length();i++){
if(str[i]<='z'&&str[i]>='a'){
temp+=str[i];
}
else{
if(temp.size()){
s.push_back(temp);
}
temp="";
}
}
int maxs=0;
for(int i=0;i<s.size();i++){
int a[27]={0};
temp=s[i];
for(int j=0;j<temp.size();j++){
int bb=temp[j]-'a';
a[bb]++;
}
for(int j=i+1;j<s.size();j++){
string temp2=s[j];
int flag=0;
for(int j=0;j<temp2.size();j++){
int cc=temp2[j]-'a';
if(a[cc]!=0){
flag=1;
break;
}
}
int zzzz=temp.size()*temp2.size();
if(flag==0) maxs=max(maxs,zzzz);
}
}
cout<<maxs;
return 0;
}
/*
["a","ab","abc","cd","bcd","abcd"]
*/