腾讯2017暑期实习生编程题
题目都比较简单,太久没做题了有点生疏反应有点慢,做题时间有点长。
一、给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。
题解:设字符串长度为n,构造另一个串为原串的回文串,求两个串的最长公共子序列的长度len即可,n-len即为答案。
#include <bits/stdc++.h> using namespace std; int dp[1005][1005]; int main() { char c1[1005],c2[1005]; while(scanf("%s",c1)!=EOF){ int len=strlen(c1);//printf("%d\n",len); for(int i=len;i>=1;i--) c1[i]=c1[i-1]; for(int i=1;i<=len;i++) c2[i]=c1[len+1-i]; //puts(c1+1);puts(c2+1); memset(dp,0,sizeof(dp)); for(int i=1;i<=len;i++) for(int j=1;j<=len;j++) { if(c1[i]==c2[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i][j-1],dp[i-1][j]); } printf("%d\n",len-dp[len][len]); } return 0; }
二、小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
你能帮帮小Q吗?
题解:先输出小写再输出大写就行了。
#include <bits/stdc++.h> using namespace std; int main() { string c; while(cin>>c){ for(int i=0;i<c.length();i++){ if(islower(c[i])) printf("%c",c[i]); } for(int i=0;i<c.length();i++){ if(isupper(c[i])) printf("%c",c[i]); } printf("\n"); } return 0; }
三、小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?
题解:首先肯定是排序,然后处理一下,开两个数组一个存数的大小,一个存数的数目。
最小值有重复数就是0,没重复就是相邻最小值,分别算一下即可。
最大值如果只有一种数那么就有C(N,2)对,否则就是第一种和最后一种数目的乘积。
也就是说要注意考虑两种特殊情况,
第一种是只有一种数的情况,单独拿出来算就行了,
第二种是有多种数但是也有重复的也就是最小值也为0。
还要注意sum数组每个都要+1,首位不要加两次。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=1e5+5; int n,cnt; ll data[N]; ll sum[N],type[N]; int main() { while(scanf("%d",&n)!=EOF) { memset(data,0,sizeof(data)); memset(sum,0,sizeof(sum)); memset(type,0,sizeof(type)); cnt=0; for(int i=0; i<n; i++) scanf("%lld",&data[i]); sort(data,data+n); type[cnt]=data[0]; ll mn=1000000000,mx=-1,ansmn=0,ansmx=0; for(int i=1; i<n; i++) if(data[i]==data[i-1]) { sum[cnt]++; if(sum[cnt]>=1) mn=0; } else type[++cnt]=data[i]; for(int i=0;i<=cnt;i++) sum[i]++; //for(int i=0;i<=cnt;i++) //printf("%lld %lld\n",type[i],sum[i]); //printf("%lld\n",mn); if(cnt==0) { ansmn=n*(n-1)/2; ansmx=ansmn; } else { if(mn==1000000000) { for(int i=1; i<=cnt; i++) mn=min(type[i]-type[i-1],mn); for(int i=1; i<=cnt; i++) if(type[i]-type[i-1]==mn) ansmn+=sum[i]*sum[i-1]; } else if(mn==0) { for(int i=0; i<=cnt; i++) ansmn+=sum[i]*(sum[i]-1)/2; } ansmx=sum[cnt]*sum[0]; } printf("%lld %lld\n",ansmn,ansmx); } return 0; } /* 6 45 12 45 32 5 6 */ // 1 2
第三题的另一种解法:
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; const int inf=0x3f3f3f3f; typedef long long ll; ll data[N],n,x; int main() { while(cin>>n) { memset(data,0,sizeof(data)); for(int i=0; i<n; i++) cin>>data[i]; sort(data,data+n); if(n==1) printf("0 0\n"); else { ll mn=data[0],mx=data[n-1];//数组最小值和最大值 if(mn==mx) { printf("%lld %lld\n",n*(n-1)/2,n*(n-1)/2); } else { ll num_mn=1,num_mx=1;//数组最小值和最大值各有多少个 for(int i=1; i<n; i++) if(data[i]==data[i-1]) num_mn++; else break; for(int i=n-2; i>=0; i--) if(data[i]==data[i+1]) num_mx++; else break; int f=0; for(int i=1; i<n; i++) { if(data[i]==data[i-1]) { f=1; break; } } //注意这里要判断最小值是不是0 如果是0就要算c(n,2)的个数 if(f) { ll ans=0,sum=1; for(int i=1; i<n; i++) { if(data[i]==data[i-1]) { sum++; } else { ans+=sum*(sum-1)/2; sum=1; } if(i==n-1) ans+=sum*(sum-1)/2; } printf("%lld %lld\n",ans,num_mn*num_mx); } else { //数组差的最小值 数组差的最小值的个数 ll ans_del_mn=inf,num_del_mn=0; for(int i=1; i<n; i++) { if(data[i]-data[i-1]<ans_del_mn) { ans_del_mn=data[i]-data[i-1]; num_del_mn=0; } if(data[i]-data[i-1]==ans_del_mn) num_del_mn++; } printf("%lld %lld\n",num_del_mn,num_mn*num_mx); } } } } return 0; }