第一题:
用STL的string的 find 和 erase:
首先,通过find找到需要删除的字符/字符串的位置:
string str;
string target;
int pos = str.find(target);
然后通过erase进行删除:
n = target.size();
str = str.erase(pos,n);
第二题:
https://www.nowcoder.com/questionTerminal/c0803540c94848baac03096745b55b9b?toCommentId=3154435
#include<iostream> using namespace std; int main(){ long long N,D; while(cin>>N>>D){ long long res=0; long long *a=new long long[N]; for(long long i=0,j=0;i<N;i++){ cin>>a[i]; while (i >= 2 && (a[i] - a[j]) > D) { j++; } res +=(i - j-1) * (i - j) / 2; } cout<<res%99997867; return 0; } }
我当时做的时候纠结的就是如何才能做到不重不漏啊(梦回高中了属于是),我的算法本来想用双循环找一串符合条件的数来Cn3的,感觉重合了,一时间想不出怎么搞就跳了,这里的话相当于锁定了一个最大数,然后让其他数来进行组合,这样的话就可以实现
这里好像是有坑的,int 还会超限。。long都不行,必须得long long。。
第三题:
雀魂启动!
我写这题的时候一直在想如何判断胡,感觉好难顶,常用函数调用还不是太熟练,而且用的是dfs,不禁令人感叹。
核心代码:
bool isHu(vector<int> nums) {//其实是一个dfs的过程 if (nums.empty()) return true;//递归出口 int cnt = count(nums.begin(), nums.begin() + 4, nums[0]);//记录与首元素相同的数字的个数 if (nums.size() % 3 != 0 && cnt >= 2) {//取雀头(只会取一次) if (isHu(vector<int>(nums.begin() + 2, nums.end()))) return true; } if (cnt >= 3) {//取刻子(三个相同的数字) if (isHu(vector<int>(nums.begin() + 3, nums.end()))) return true; } if (count(nums.begin(), nums.end(), nums[0] + 1) > 0 && count(nums.begin(), nums.end(), nums[0] + 2) > 0) {//取顺子 int val = nums[0]; nums.erase(nums.begin());//去掉一个首元素(顺子的第一个) nums.erase(find(nums.begin(), nums.end(), val + 1));//去掉一个首元素+1(顺子的第二个) nums.erase(find(nums.begin(), nums.end(), val + 2));//去掉一个首元素+2(顺子的第三个) if (isHu(nums)) return true; } return false; }
for (int i = 1; i <= 9; ++i) {//遍历下一张可能的牌 if (count(nums.begin(), nums.end(), i) == 4) continue;//最多就4张,真的不能再多了 nums.insert(lower_bound(nums.begin(), nums.end(), i), i);//插入i,函数lower_bound()在first和last中的前闭后开区间,进行二分查找。返回从first开始的第一个大于或等于val的元素的地址。如果所有元素都小于val,则返回last的地址。注意:数组必须是排好序的数组。 if (isHu(nums)) res.push_back(i); //判断是否ok nums.erase(lower_bound(nums.begin(), nums.end(), i));//恢复原始nums数组 }
第四题:
特征提取
https://www.nowcoder.com/questionTerminal/5afcf93c419a4aa793e9b325d01957e2?answerType=1&f=discussion
核心知识:map,pair
用双字典轮滚解决
用一个老字典和一个新字典,最后的时候把老的换成新的,新的变空等待输入,这种方法适用于过去数据要传递到未来的情况。(连续问题)
#include<bits/stdc++.h> using namespace std; int main(){ int N,m; cin>>N; while(N--){ cin>>m; int f,x,y; map<pair<int,int>,int> pre;//历史帧数 map<pair<int,int>,int> now;//现在帧数 int max_ = 0; for(int i =0; i< m;i++){ cin>>f; for(int j =0; j< f;j++){ cin>>x>>y; if(pre.count({x,y})){ now[{x,y}] = pre[{x,y}] + 1;//又出现了一次,就是老的加1 }else{ now[{x,y}] = 1;//从来没有出现过 } if(now[{x,y}]>max_){//时时更新任何一个连续帧 max_ = now[{x,y}]; } } //如果这帧为0,那么就不会保留任何历史信息了,因为now在这轮没有任何内容。 pre.clear();//清空历史,把now变为历史 pre.swap(now);//now 置空,同时,now变成上一个,这样的话连续问题就可以解决 } cout<<max_<<endl; } return 0; }
// 查询关键字为key的元素的个数,在map里结果非0即1
size_t count( const Key& key ) const; //
第五题:
https://www.nowcoder.com/questionTerminal/3d1adf0f16474c90b27a9954b71d125d?answerType=1&f=discussion
第一篇题解,很详细。
他的代码没有注释,所以写一下基于注释的代码
// 代码 #include<bits/stdc++.h> using namespace std; int main() { int n; cin >> n; vector<vector<int> > cost(n,vector<int>(n));//初始化 for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin >> cost[i][j];//输入 int all = 1<<(n-1);//位运算,取2个n-1次方 vector<vector<int> > dp(n,vector<int>(all));//初始化 for(int i=0;i<n;i++) dp[i][0] = cost[i][0];//因为题目要求返回原点 for(int j=1;j<all;j++){ for(int i=0;i<n;i++){ dp[i][j] = INT_MAX;//取最大值防止。。 if(((j>>(i-1))&1)==0){ for(int k=1;k<n;k++){ if(((j>>(k-1))&1)==1){ dp[i][j] = min(dp[i][j],cost[i][k]+dp[k][j^(1<<(k-1))]); }//带着循环看。就是取这几个的最小值。 } } } } cout << dp[0][all-1] << endl; }
第六题:
略。
第七题:
机器人跳跃问题
数学归纳法了属于是
方法一:
归纳:
#include<iostream> #include<vector> #include<cmath> using namespace std; int main(){ int N; int ans = 0; cin >> N; vector<int>D(N,0); for(int i = 0;i<N;i++) cin >>D[i]; for(auto i in D){ ans+=D[i]/pow(2,i); } cout<<ans<<endl; return 0; }
方法二,逆着解。
#include<iostream> #include<vector> #include<cmath> using namespace std; int main(){ int N; int ans = 0; cin >> N; vector<int>D(N,0); for(int i = 0;i<N;i++) cin >>D[i]; for(int j=N-1;j>=0;j--){ ans = ceil((D[j]+ans)/2.0);//注意c++中除法整数/整数为0,ceil向上取整要整数/float类型 } cout<<ans<<endl; return 0; }
差不多就这样吧,焯!