拼多多 8月5日 算法岗笔试题
题目1:字符串矩形输出
思路:计算出每行长度,然后分四次将字符加到每条边上,注意str.size()/4+1等于矩形边长。
AC
#include<iostream>
#include<string>
using namespace std;
char lst[15][15];
int main(){
string str;
while(cin>>str){
memset(lst,0,sizeof(lst));
int n = str.size()/4;
int pos = 0;
for(int i = 0;i<n;i++) //左上到右上
lst[0][i] = str[pos++];
for(int i = 0;i<n;i++) //右上到右下
lst[i][n] = str[pos++];
for(int i = 0;i<n;i++) //右下到左下
lst[n][n-i] = str[pos++];
for(int i = 0;i<n;i++) //左下到左上
lst[n-i][0] = str[pos++];
for(int i = 0;i<=n;i++){
for(int j = 0;j<=n;j++){
if(lst[i][j]==0)
cout<<" ";
else
cout<<lst[i][j];
}
cout<<endl;
}
}
system("pause");
return 0;
}
题目2:字符串转数字,加小数点
思路:首先考虑字符串长度为0和1的情况,输出0;然后是字符串长度>=2的情况,定义函数kind,返回当前字符串可以加小数点的种类数。
AC
#include<iostream>
#include<string>
#include<bits/stdc++.h>
using namespace std;
int kind(string st){
if(st[0]=='0'&&st[st.size()-1]=='0'){ //字符串首尾都是0
if(st.size()==1) //若长度为1,则只有一种情况,不加小数点,为0,返回1
return 1;
else //若长度大于1,则当前不存在符合条件的情况,返回0
return 0;
}
else if(st[0]!='0'&&st[st.size()-1]!='0') //字符串首尾都不为0,则小数点共有str.size()种加法:如xxx:"xxx";"xx.x";"x.xx"3种
return st.size(); //返回str.size()
else //字符串首尾有一个为0,则只有一种情况:首为0,将小数点加到第一个不为0的数前面;尾为0,不加小数点
return 1; //返回1
}
int main(){
string str;
while(cin>>str){
if(str.size()<=1)
cout<<0<<endl;
else{
int sum = 0;
for(int i = 1;i<str.size();i++){
string str1(str.begin(),str.begin()+i);
string str2(str.begin()+i,str.end());
int a = kind(str1);
int b = kind(str2);
sum += kind(str1)*kind(str2); //两个数字的种数乘积的和,即为结果
}
cout<<sum<<endl;
}
}
system("pause");
return 0;
}
题目3:最亲密的非朋友
思路:将输入存储到n*n的数组中,设要求的是i,将i行循环一遍,将每个和i不是朋友的取出来,与i的朋友进行比较,然后找出相似性最大的。
输入的时候,用到getline,要先getline一次,才能正常输入
AC
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
int lst[105][105];
int main(){
int n,m;
while(cin>>n>>m){
string s1;
getline(cin,s1); //先getline一次,保证后面正常输入
for(int i = 0;i<n;i++){
string s;
getline(cin,s); //正常输入一行
s+=" ";
int sum = 0;
for(int j = 0;j<s.size();j++){ //将string中的数字提取出来,赋值
if(s[j]!=' ')
sum = sum*10+s[j]-'0';
else{
lst[i][sum] = 1;
sum = 0;
}
}
}
int pos = -1;
int sum = INT_MIN;
for(int i = 0;i<n;i++){
if(m!=i&&lst[m][i]==0){
int temp = 0;
for(int j = 0;j<n;j++){
if(lst[m][j]==1&&lst[i][j]==1)
temp++;
}
if(temp>sum){
sum = temp;
pos = i;
}
}
}
cout<<pos<<endl;
}
system("pause");
return 0;
}
题目4:递增递减子序列
思路:考虑顺序循环两遍,一次保存包含当前位的最长递增子序列长度,一次保存包含当前位的最长递减子序列长度,然后找出当前位的递增和递减长度最大且递增与递减长度差最大的位置,根据递增和递减长度的大小,决定是删除递增序列,还是递减序列,每删除一次,num++。外部加一个while循环,判断原始输入是否已经都删除完。都删除完后,num的值即为操作次数。
贪心算法,应该不是最终解法。
20%
#include<iostream>
#include<vector>
using namespace std;
int lst1[55];
int lst2[55];
int main(){
int n;
while(cin>>n){
int num = 0;
vector<int> org;
for(int i = 0;i<n;i++){
int x;
cin>>x;
org.push_back(x);
}
while(!org.empty()){
n = org.size();
memset(lst1,0,sizeof(lst1)); //保存包含当前值的最长递增子序列长度
memset(lst2,0,sizeof(lst2)); //保存包含当前值的最长递减子序列长度
lst1[0] = 1; //赋初值
for(int i = 1;i<n;i++){
int temp = 0;
for(int j = 0;j<i;j++){
if(org[j]<org[i])
temp = temp>lst1[j]?temp:lst1[j]; //最长递增子序列
}
lst1[i] = temp+1;
}
lst2[0] = 1; //赋初值
for(int i = 1;i<n;i++){
int temp = 0;
for(int j = 0;j<i;j++){
if(org[j]>org[i])
temp = temp>lst2[j]?temp:lst2[j]; //最长递减子序列
}
lst2[i] = temp+1;
}
int ma = 0;
int pos = 0;
int dif = 0;
for(int i = 0;i<n;i++){
int x = lst1[i]+lst2[i];
int y = abs(lst1[i]-lst2[i]);
if(x>=ma&&dif<y){ //递增递减长度和最大且差值最大
ma = x;
pos = i;
dif = y;
}
}
if(lst1[pos]>lst2[pos]){ //删除最长递增序列
while(lst1[pos]!=1){ //逆序查找包含当前位置的最长递增序列的所有位置,并删除
for(int i = pos-1;i>=0;i--){
if(org[i]<org[pos]&&lst1[i]==lst1[pos]-1){
org.erase(org.begin()+pos,org.begin()+pos+1);
pos = i;
break;
}
}
}
org.erase(org.begin()+pos,org.begin()+pos+1);
}
else{ //删除最长递减序列
while(lst2[pos]!=1){ //逆序查找包含当前位置的最长递减序列的所有位置,并删除
for(int i = pos-1;i>=0;i--){
if(org[i]>org[pos]&&lst2[i]==lst2[pos]-1){
org.erase(org.begin()+pos,org.begin()+pos+1);
pos = i;
break;
}
}
}
org.erase(org.begin()+pos,org.begin()+pos+1);
}
num++;
}
cout<<num<<endl;
}
system("pause");
return 0;
}
#拼多多##笔试题目##算法工程师#

