牛客春招刷题训练营 - 3.21题解 | C++
活动地址: 牛客春招刷题训练营 - 编程打卡活动
简单题:字符串加密
【模拟】【set】
“去重”一般使用STL的set比较方便,出现过了就插入集合。
然后按照题目要求模拟即可。
#include <iostream>
#include <set>
using namespace std;
int main() {
string s, t;
cin >> s >> t;
string p = "";
set<char> vis;
for(char c: s) {
if(vis.count(c)) continue;
vis.insert(c);
p += c;
}
for(char c='a'; c<='z'; c++) {
if(!vis.count(c)) {
p += c;
}
}
for(char c: t) {
cout << p[c-'a'];
}
return 0;
}
中等题:从单向链表中删除指定值的节点
【链表】
链表模版题,其实虽然我个人写链表都是直接上来就写双向链表,因为双向的功能比单向要全面。
不过这道题的标题里就要求用“单向链表”,那就讲一下单向链表的做法。
首先观察到这道题插入数值的范围是1e4,那就不需要离散化了,直接开个1e4的数组就好。
然后因为考虑到题给的头结点h也是可能被删除的,所以为了方便起见,我手动引入了一个头结点,值为0(肯定不会和插入的节点重复)。最后按普遍习惯,把-1作尾结点。
然后其实就是比较基础的单向链表的模板,就不赘述了。不熟悉的小伙伴请自行去补充知识点。
#include <iostream>
#include <vector>
using namespace std;
const int N = 1e4+5;
int nxt[N];
int main() {
int n;
cin >> n;
int h;
cin >> h;
nxt[0] = h;
nxt[h] = -1;
for(int i=1; i<n; i++) {
int a, b;
cin >> a >> b;
nxt[a] = nxt[b];
nxt[b] = a;
}
int k;
cin >> k;
for(int i=0; i!=-1; i=nxt[i]) {
if(nxt[i] == k) {
nxt[i] = nxt[k];
break;
}
}
for(int i=0; i!=-1; i=nxt[i]) {
if(i != 0) cout << i << " ";
}
return 0;
}
困难题:走方格的方案数
【dp】【组合数学】
这道题一看数据范围只有8,有点离谱。
那应该瞎搞都能暴力做出来。不过这其实是比较典的题,也算是dp经典过河卒模型的基础版。
先来dp写一下吧,复杂度是O(N^2)。
状态转移为:一个点的方案始终等于到上一个点的可能方案之和。由于只能向下或者向右,所以一个点(i, j)的上一个点要么是(i-1, j),(i, j-1),所以dp[i][j] = dp[i][j-1] + dp[i-1][j];。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> dp(n+5, vector<int>(m+5));
for(int i=0; i<=n; i++) {
dp[i][0] = 1;
}
for(int j=0; j<=m; j++) {
dp[0][j] = 1;
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
dp[i][j] = dp[i][j-1] + dp[i-1][j];
}
}
cout << dp[n][m] << endl;
return 0;
}
不过这道题最优解是O(N)的做法,也是一个比较典的思想。
不难想到,从起点走到终点一定是n次向下+m次向右。
不妨将其转化为一个模型:n个0和m个1组成01序列有多少种组合方法。每种01序列其实就对应着唯一一条路径。
而对于“n个0和m个1组成01序列有多少种组合方法”的解其实就是C(n+m, n)或者C(n+m, m)。所以组合数公式套一下就行了。
fac[i]表示i的阶乘,因为i最大可能到16,所以要开long long。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<long long> fac(n+m+1);
fac[0] = 1;
for(int i=1; i<=n+m; i++)
fac[i] = fac[i-1] * i;
// C(n+m, n)
cout << fac[n+m]/(fac[n]*fac[m]) << endl;
return 0;
}
#牛客春招刷题训练营#
查看13道真题和解析