【美团点评】2020校招系统开发方向笔试题
还是只写了编程题。这套题写了大概一个半小时。。下午刚做完的。
还是有点难。。QAQ我不会字符串是真的/
试题链接:2020校招系统开发方向笔试题
7、 大数加法
题意:以字符串的形式读入两个数字,再以字符串的形式输出两个数字的和。
题解:这题我做过!!!之前用java参加蓝桥杯的时候学过23333(应该是说自从那次去参加湖北今日头条杯,场上压8位精度c++板子被草之后回来就去学了java大数。。。)
java的大整数类的应用,详情可以看链接,里面有很多java的常见用法。
这题的坑点是,它的引号是当作字符输入的。。!QAQ所以要去除引号。
代码:
1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main{ 5 public static void main(String[] args) { 6 Scanner scanner = new Scanner(System.in); 7 String num1 = scanner.nextLine(); 8 String num2 = scanner.nextLine(); 9 num1 = num1.substring(1,num1.length()-1); 10 num2 = num2.substring(1,num2.length()-1); 11 //初始化 12 BigInteger n1 = new BigInteger(num1); 13 BigInteger n2 = new BigInteger(num2); 14 15 //System.out.println(n1); 16 //System.out.println(n2); 17 BigInteger sum = n1.add(n2); //加 18 19 System.out.println("\""+sum+"\""); 20 } 21 22 }
8、 回文子串
题意:给定一个字符串,你的任务是计算这个字符串中有多少个回文子串(回文串是一个正读和反读都一样的字符串)。
具有不同开始位置或结束位置的回文串,即使是由相同的字符组成,也会被计为是不同的子串。
题解:这个题就是最长回文子串的变形,我们做一个统计就可以,最长回文子串可以看链接。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1010; 4 int dp[maxn][maxn] = {0}; 5 6 int main(){ 7 string s; 8 cin>>s; 9 int len = s.size(); 10 int cnt = 0; 11 cnt += len; 12 for(int i = 0; i < len ;i++){ 13 dp[i][i] = 1; 14 if(s[i] == s[i+1]){ 15 dp[i][i+1] = 1; 16 cnt++; 17 } 18 } 19 for(int pos = 3; pos<=len ; pos++){ 20 for(int i = 0 ;i <= len-pos; i++){ 21 int j = i+pos-1; 22 if(dp[i+1][j-1] && s[i] == s[j]){ 23 dp[i][j]=1; 24 cnt++; 25 } 26 } 27 } 28 29 cout<<cnt<<endl; 30 31 return 0; 32 }
9、合并金币
题意:有 N 堆金币排成一排,第 i 堆中有 C[i] 块金币。每次合并都会将相邻的两堆金币合并为一堆,成本为这两堆金币块数之和。经过N-1次合并,最终将所有金币合并为一堆。请找出将金币合并为一堆的最低成本。
其中,1 <= N <= 30,1 <= C[i] <= 100
题解:以前打比赛训练的时候有做过一道叫做合并石子的题。一道经典的区间dp应用。
其实之前最先做这个题我是用贪心,但是明显贪心不对。因为这是选择相邻的两堆金币。
我们用dp[l][r]表示l到r区间合并的最小值。接下来就是划分子问题。
我们将[l,r]区间做一个k的划分,以k为分界点,可以划分成[l,k]和[k+1,r](所以k不能枚举到r啦)
这样就能得到状态转移方程 dp[l][r] = min(dp[l][r],dp[l][k] + dp[k+1][r] + cost[l][r])
这里的花费就是合并金币所需要的花费。从[l,r]的花费也就是金币总个数(做初始化即可)/
(补了一下注释,虽然也没啥)这种题目还有很多变种类型,优化也有很多。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 105; 4 5 int n; 6 int num[maxn]={0}; 7 int dp[maxn][maxn]={0}; 8 int cost[maxn][maxn]={0}; 9 10 int main(){ 11 cin>>n; 12 for(int i = 1;i <= n;i++) cin>>num[i]; 13 14 memset(dp,0x3f,sizeof(dp)); 15 16 //花费初始化 17 for(int i = 1; i <= n;i++){ 18 for(int j = i; j <= n ;j++){ 19 for(int k = i; k <= j; k++){ 20 cost[i][j] += num[k]; 21 } 22 } 23 } 24 25 for(int i = 1; i <= n ;i++) dp[i][i] = 0; 26 27 //枚举k [l,r]->[l,k]+[k+1,r] 28 for(int len = 2; len <= n;len++){ 29 for(int l = 1; l <= n-len+1 ;l++){ 30 int r = l+len-1; 31 for(int k = l ; k < r; k++){ 32 dp[l][r] = min(dp[l][r],dp[l][k] + dp[k+1][r]+cost[l][r]); 33 } 34 } 35 } 36 37 cout<<dp[1][n]<<endl; 38 return 0; 39 }
10、最小唯一前缀
题意:给定一组个字符串,为每个字符串找出能够唯一识别该字符串的最小前缀。
题解:当时脑子里想到是字典树,但是不信邪,要去做暴力。。但是暴力的不够优美。。
于是上了板子3分钟就AC了。/trie树真的很好用。。准备多做字符串的题了。。我字符串真的好弱。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 105; 5 const int maxnode = 100005; 6 7 string str[maxn]; 8 9 int ch[maxn][maxn]; 10 char val[maxn]; 11 12 struct Trie { 13 int sz; 14 Trie() { 15 sz = 1; 16 memset(ch[0], 0, sizeof(ch[0])); 17 } 18 int idx(char c) { return c - 'a'; } 19 20 void insert(string s) { 21 int u = 0; 22 int n = s.size(); 23 for(int i = 0; i < n; i++) { 24 int c = idx(s[i]); 25 if(!ch[u][c]) { 26 memset(ch[sz], 0, sizeof(ch[sz])); 27 val[sz] = 0; 28 ch[u][c] = sz++; 29 } 30 u = ch[u][c]; 31 val[u]++; 32 } 33 } 34 35 void query(string s) { 36 int u = 0; 37 int n = s.size(); 38 for(int i = 0; i < n; i++) { 39 putchar(s[i]); 40 int c = idx(s[i]); 41 if(val[ch[u][c]] == 1) return ; 42 u = ch[u][c]; 43 } 44 } 45 }; 46 47 int main() { 48 Trie trie; 49 int n; 50 cin>>n; 51 for(int i = 0;i < n ;i++){ 52 cin>>str[i]; 53 trie.insert(str[i]); 54 } 55 for(int i = 0; i < n; i++) { 56 trie.query(str[i]); 57 cout<<endl; 58 } 59 return 0; 60 }