第一題:鏈接: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"]
*/