当前位置: 首页 > news >正文

笔试强训:Week -2

目录

一*、大数加法(高精度加法模拟)

二*、链表相加(高精度加法模拟)

三*、大数乘法(高精度乘法模拟)

四*、求最小公倍数(数学)

五、数组中的最长连续子序列(排序+双指针)

六、字母收集(路径dp)

七、添加逗号(模拟)

八、跳台阶(dp斐波那契数列模型)

九、扑克牌顺子(排序+模拟 /位图+模拟)

十、最长回文子串(动规回文串问题)

十一、买卖股票的最佳时机I (贪心)

十二、过河卒(路径dp)

十三?、游游的水果大礼包(枚举)

十四、买卖股票的最佳时机II(双指针/贪心/简单多状态dp)

十五?、倒置字符串(双指针)

十六、删除公共字符(哈希表)

十七、两个链表的第一个公告结点(双指针)

十八*、mari和shiny(状态dp+空间优化)


一*、大数加法(高精度加法模拟)

大数加法_牛客题霸_牛客网

    string solve(string s, string t) {int m=s.size(),n=t.size();string ret;int sum=0,cur1=m-1,cur2=n-1;while(cur1>=0||cur2>=0||sum){if(cur1>=0){sum+=s[cur1]-'0';--cur1;}if(cur2>=0){sum+=t[cur2]-'0';--cur2;}ret+=to_string(sum%10);sum/=10;}reverse(ret.begin(),ret.end());return ret;}

二*、链表相加(高精度加法模拟)

链表相加(二)_牛客题霸_牛客网

逆转链表,然后模拟

    ListNode* ReverseNode(ListNode*head){if(!head||!head->next)return head;ListNode* newhead=ReverseNode(head->next);head->next->next=head;head->next=nullptr;return newhead;}// ListNode* ReverseNode(ListNode*head)// {//     ListNode*prev=nullptr;//     ListNode*cur=head;//     while(cur)//     {   //         ListNode*t=cur->next;//         cur->next=prev;//         prev=cur;//         cur=t;//     }//     return prev;// }ListNode* addInList(ListNode* head1, ListNode* head2) {//逆转链表ListNode*cur1=ReverseNode(head1),*cur2=ReverseNode(head2);int add=0;ListNode*newhead=new ListNode(-1);while(cur1||cur2||add){if(cur1){add+=cur1->val;cur1=cur1->next;}if(cur2){add+=cur2->val;cur2=cur2->next;}//头插ListNode*Node=new ListNode(add%10);Node->next=newhead->next;newhead->next=Node;add/=10;}ListNode*prev=newhead->next;delete newhead;return prev;}

三*、大数乘法(高精度乘法模拟)

大数乘法_牛客题霸_牛客网

    string solve(string s, string t) {if(s=="0"||t=="0")return "0"; int m=s.size(),n=t.size();vector<int> res(m+n);for(int i=m-1;i>=0;--i){for(int j=n-1;j>=0;--j){int p1=i+j,p2=i+j+1;int mul=(s[i]-'0')*(t[j]-'0');int sum=mul+res[p2];res[p2]=sum%10;res[p1]+=sum/10;}} string ret;for(int i=0;i<m+n;++i){if(ret.empty()&&res[i]==0)continue;ret+=to_string(res[i]);}return ret;}

四*、求最小公倍数(数学)

求最小公倍数_牛客题霸_牛客网

先求最大公约数tmp,那么返回a*b/tmp即可

求最大公约数有以下两种方法:
1:暴力枚举

#include <iostream>
using namespace std;int main() {int a, b;cin>>a>>b;int n=min(a,b),tmp;for(int i=n;i>=1;--i){if(a%i==0&&b%i==0){tmp=i;break;}}cout<<a*b/tmp;return 0;
}

2.辗转相除法(非常高效,学习)

#include <iostream>
using namespace std;int gcd(int a,int b)
{if(b==0)return a;return gcd(b,a%b);
}
int main() {int a, b;cin>>a>>b;cout<<a*b/gcd(a,b)<<endl;return 0;
}

五、数组中的最长连续子序列(排序+双指针)

数组中的最长连续子序列_牛客题霸_牛客网

看完题解以及示例一之后,其实也就可以转换成双指针问题了,记得先排序,

此外,示例2在暗示我们,如果后一个数和前一个数一样,都记作一次

所以用例没过的时候一定要看看你忽略的示例,示例一定是有意义的。

六、字母收集(路径dp)

字母收集_牛客题霸_牛客网

先创建一个int数组表,存信息,l的话就代表4,o就代表3

然后正常dp就行,很简单,不过自己想出来了很开心。

#include <iostream>
#include <vector>
using namespace std;int main() {int n,m;cin>>n>>m;vector<vector<int>> num(n,vector<int>(m));char ch;for(int i=0;i<n;++i){for(int j=0;j<m;++j){cin>>ch;if(ch=='l')num[i][j]=4;else if(ch=='o')num[i][j]=3;else if(ch=='v')num[i][j]=2;else if(ch=='e')num[i][j]=1;}}vector<vector<int>> dp(n+1,vector<int>(m+1));for(int i=1;i<=n;++i){for(int j=1;j<=m;++j){//注意映射dp[i][j]=num[i-1][j-1];dp[i][j]+=max(dp[i-1][j],dp[i][j-1]);}}cout<<dp[n][m];return 0;
}

上面是自己写的思路很清晰,也可以按下面这种方法写

#include <iostream>
using namespace std;
const int N=501;
char nums[N][N];
int dp[N][N];
int main() {int m,n;cin>>n>>m;for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>nums[i][j];for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){int t=0;if(nums[i][j]=='l') t=4;else if(nums[i][j]=='o') t=3;else if(nums[i][j]=='v') t=2;else if(nums[i][j]=='e') t=1;dp[i][j]=max(dp[i-1][j],dp[i][j-1])+t;}cout<<dp[n][m]<<endl;return 0;
}
// 64 位输出请用 printf("%lld")

七、添加逗号(模拟)

添加逗号_牛客题霸_牛客网

斗宗强者恐怖如斯,本人写的代码丑陋无比写了三十多行,(begin存下标然后不断取substr)没想到标答这么简洁。

#include <iostream>
using namespace std;int main() {string s;cin>>s;string ret;//统计最后结果int n=s.size();for(int i=0;i<n;++i){ret+=s[i];if((n-i-1)%3==0&&i!=n-1) ret+=',';}cout<<ret<<endl;return 0;
}
// 64 位输出请用 printf("%lld")

本人写的,貌似不用判断前导0???还真是,修改了一下代码,/(ㄒoㄒ)/~~

#include <iostream>
using namespace std;int main() {string N;cin>>N;int n=N.size();int begin=0;if(n<=3){cout<<N.substr(begin,n);return 0;}string ret;if(n%3)ret+=(N.substr(begin,n%3)+",");begin+=n%3;while(begin+2<n){ret+=N.substr(begin,3);begin+=3;if(begin<n)ret+=",";}cout<<ret<<endl;return 0;
}

八、跳台阶(dp斐波那契数列模型)

跳台阶_牛客题霸_牛客网

很简单第一题,这里直接上空间优化代码

注意特判

#include <iostream>
using namespace std;int main() {int n;cin>>n;if(n==1||n==2){cout<<n;return 0;}int a=1,b=2,c;for(int i=3;i<=n;++i){c=a+b;a=b;b=c;}cout<<c;return 0;
}

九、扑克牌顺子(排序+模拟 /位图+模拟)

扑克牌顺子_牛客题霸_牛客网

法一:排序+模拟,自己想出来了很开心

排序,边遍历边统计0的个数count,非0元素统计一下下一个元素减去这个元素再减去1,就是这期间需要填补的数gap,最后判断count==gap?出错->只考虑了非零元素区间,如果非零元素区间刚好是+1+1递增,只需把0修改一下就行,也是符合的,所以应该是count>=gap。还是没全部通过,查看用例,具有相同元素会就是false,此时gap会等于-1,如果遇到这种情况直接返回false即可。大功告成。

bool IsContinuous(vector<int>& numbers) {sort(numbers.begin(), numbers.end());int count = 0, gap = 0, cur = 0;while (cur < 5) {if (numbers[cur] == 0) {++count;++cur;} else {if (cur + 1 < 5) {int x=numbers[cur + 1] - numbers[cur] - 1;if(x<0)return false;gap += x;}++cur;}}return count >= gap;}

法二:找规律+位图

看完思路也是直呼666

class Solution {
public:bool IsContinuous(vector<int>& nums) {int flag=0;int _min=14,_max=0;for(auto&e:nums){if(e==0) continue;if(flag&(1<<e)) return false;//说明重复了flag|=(1<<e);//标记这张票出现过了_min=min(_min,e);//最小牌_max=max(_max,e);//最大牌}return _max-_min<5;}
};

十、最长回文子串(动规回文串问题)

最长回文子串_牛客题霸_牛客网

不久前一刷过这题,再次碰见完全没思路了

在动规专栏里有总结回文串问题->动态规划回文串问题汇总

dp[i][j]表示i~j闭区间,是否是回文串,判断是不是就从两端不断往内,

如果s[i]==s[j],如果i==j,返回true,如果i恰好是j左边一个数也就是i+1==j返回true

其他情况就要看dp[i+1][j-1],因为需要后边的数据,所以i层需要倒着填

    int getLongestPalindrome(string A) {int n=A.size();vector<vector<bool>> dp(n,vector<bool>(n));int len=1;for(int i=n-1;i>=0;--i){for(int j=i;j<n;++j){//默认就是false这里不用再写//if(A[i]!=A[j])dp[i][j]=false;if(A[i]==A[j])dp[i][j]=i+1<j?dp[i+1][j-1]:true;if(dp[i][j]&&len<j-i+1)len=j-i+1;}}return len;}

十一、买卖股票的最佳时机I (贪心)

买卖股票的最好时机(一)_牛客题霸_牛客网

笔试场上只想到暴力,实在不应该。遍历中途不断更新0~当前位置最小值,然后ret=max(ret,num[i]-prevMin)

#include <iostream>
using namespace std;
const int N=1e5+1;
int num[N];
int main() {int n;cin>>n;for(int i=0;i<n;++i)cin>>num[i];int prevMin=num[0],ret=0;for(int i=1;i<n;++i){int jud=num[i]-prevMin;if(jud>ret)ret=jud;prevMin=min(prevMin,num[i]);}cout<<ret;return 0;
}

十二、过河卒(路径dp)

[NOIP2002 普及组] 过河卒_牛客题霸_牛客网

看完就能明白是很明显的路径dp,dp值表示到达该点的总路线条数,遇到拦截点置0,dp值等于上+左。但是注意马不能直着走,判断距离的时候映射的位置不能在同一行,同一列。

此外,int会爆,保险还是开long long

#include <iostream>
using namespace std;
#include<vector>
#include<cmath>
int main() {int n,m,x,y;cin>>n>>m>>x>>y;vector<vector<long long>> dp(n+2,vector<long long>(m+2));dp[0][1]=1;for(int i=1;i<=n+1;++i){for(int j=1;j<=m+1;++j){//注意映射,也可以循环外x,y都+=1这样就不用老是写减1if(i-1==x&&j-1==y)dp[i][j]=0;//马不能直着走else if(i-1!=x&&j-1!=y&&abs(i-1-x)+abs(j-1-y)==3)dp[i][j]=0;else dp[i][j]=dp[i-1][j]+dp[i][j-1];}}cout<<dp[n+1][m+1];return 0;
}

十三?、游游的水果大礼包(枚举)

游游的水果大礼包

其实按贪心也是能写的,不过没枚举这么简洁,还不如直接枚举

made这里int会爆,要开long long,之后看到即使只有相加都要想到先开long long

#include<iostream>
using namespace std;
int main(){long long n,m,a,b;cin>>n>>m>>a>>b;long long ret=0;//我们先尝试枚举1号for(int x=0;x<=min(n/2,m);++x){int y=min(n-x*2,(m-x)/2);ret=max(ret,a*x+b*y);}cout<<ret<<endl;
}

十四、买卖股票的最佳时机II(双指针/贪心/简单多状态dp)

买卖股票的最好时机(二)_牛客题霸_牛客网

解法一:双指针:

#include <iostream>
using namespace std;
const int N=1e5+3;
int a[N];
int n;
int main() {cin>>n;int ret=0;for(int i=0;i<n;++i) cin>>a[i];for(int i=0;i<n;++i){int j=i;while(j+1<n&&a[j+1]>a[j]) ++j;//此时j正好在顶点ret+=a[j]-a[i];i=j;}cout<<ret<<endl;
}
// 64 位输出请用 printf("%lld")

解法二:贪心,有正收益我就加,相当于是解法一的思路拆分成一天一天

#include <iostream>
using namespace std;
const int N=1e5+3;
int a[N];
int n;
int main() {cin>>n;int ret=0;for(int i=0;i<n;++i) cin>>a[i];for(int i=1;i<n;++i)if(a[i]>a[i-1]) ret+=a[i]-a[i-1];cout<<ret<<endl;
}
// 64 位输出请用 printf("%lld")

解法三:简单多状态dp,f表示买入状态最大利润,g表示卖出状态最大利润

#include <iostream>
using namespace std;
const int N=1e5+1;
int f[N],g[N],price[N];
int main() {int n;cin>>n;for(int i=0;i<n;++i)cin>>price[i];f[0]=-price[0];for(int i=1;i<=n;++i){f[i]=max(f[i-1],g[i-1]-price[i-1]);g[i]=max(g[i-1],f[i-1]+price[i-1]);}cout<<g[n];return 0;
}

十五?、倒置字符串(双指针)

倒置字符串_牛客题霸_牛客网

刷过一遍就理解了,这种题目就得先刷一遍,╰(艹皿艹 )。先整体逆转,再局部逆转即可

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;int main() {string s;//先整体逆置 在局部逆置getline(cin,s);reverse(s.begin(),s.end());int n=s.size();for(int left=0;left<n;++left){int right=left;while(right<n&&s[right]!=' ') ++right;//开始逆置reverse(s.begin()+left,s.begin()+right);left=right;}cout<<s<<endl;
}
// 64 位输出请用 printf("%lld")

十六、删除公共字符(哈希表)

删除公共字符_牛客题霸_牛客网

因为原字符串有空格,cin读取不到空格,所以我们用getline

#include <iostream>
using namespace std;
#include<unordered_map>
int main() {    string s1,s2;//空格也要读取getline(cin,s1);getline(cin,s2);unordered_map<char, int> hash;for(auto ch:s2)hash[ch]++;int n=s1.size();string ret;for(int i=0;i<n;++i){if(!hash.count(s1[i]))ret+=s1[i];}cout<<ret;return 0;
}

注意这里哈希表可以用数组模拟

#include <iostream>
using namespace std;
int main() {string s,t;getline(cin,s);getline(cin,t);bool hash[128]={0};for(char ch:t) hash[ch]=true;string ret;for(auto&ch:s) if(!hash[ch]) ret+=ch;cout<<ret;return 0;
}

十七、两个链表的第一个公告结点(双指针)

两个链表的第一个公共结点_牛客题霸_牛客网

之前刷抖音的时候刷到过这题hehehe

/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}
};*/
#include <cmath>
class Solution {
public:ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {if(!pHead1||!pHead2)return nullptr;ListNode*cur1=pHead1,*cur2=pHead2;//用题给最大次数当作循环条件int n=1000;while(n--){//可能存在没有公共结点的情况,所以在相等时才返回if(cur1==cur2)return cur1;cur1=cur1->next?cur1->next:pHead2;cur2=cur2->next?cur2->next:pHead1;}return nullptr;}
};

十八*、mari和shiny(状态dp+空间优化)

mari和shiny

总感觉编题目的有点皮皮的o(* ̄▽ ̄*)o

最先想到的当然是暴力咯,不过只能通过百分之40用例,超时了

#include <iostream>
using namespace std;int main() {int n;cin>>n;string s;cin>>s;int count=0;for(int i=0;i<n-2;++i){if(s[i]=='s'){for(int j=i+1;j<n-1;++j){if(s[j]=='h'){for(int k=j+1;k<n;++k){if(s[k]=='y')++count;}}}}}cout<<count;return 0;
}

下面我们用dp优化。

唉,做的时候也往这方面想了,但就是不知道代码怎么写,不得不说这代码真是太妙了

#include<iostream>
#include<string>
using namespace std;
int main(){int n;string str;cin>>n>>str;long long s=0,h=0,y=0;for(int i=0;i<n;++i){char ch=str[i];if(ch=='s')++s;else if(ch=='h')h+=s;else if(ch=='y')y+=h;}cout<<y<<endl;
}

第二周完结撒花\^o^/

Week2 ending...

http://www.dtcms.com/a/495218.html

相关文章:

  • webpack - 单独打包指定JS文件(因为不确定打出的前端包所访问的后端IP,需要对项目中IP配置文件单独拿出来,方便运维部署的时候对IP做修改)
  • 有的网站打开的是html结尾的路径有的不是wordpress放在二级目录
  • 展示型企业网站设计方案2016年做网站能赚钱
  • 【论文精读】RD-Agent-Quant:基于多智能体框架的量化因子与模型研发自动化系统
  • 网站开发大概价格建设电子商务网站流程
  • Python 练习脚本(从基础到高级150个练习)
  • GDDR6总结(1)-背景及优劣
  • Redis 中文学习手册
  • 网站改版 程序变了 原来的文章内容链接地址 打不开怎么办以百度云做网站空间
  • iOS 混淆工具链实战,多工具组合完成 IPA 混淆与加固(iOS混淆|IPA加固|无源码混淆|App 防反编译)
  • 莞城做网站wordpress 插件数据
  • YouTube 视频评论,并插入 MySQL
  • mac idea 点击打开项目卡死
  • 网站建设座谈会上的发言wordpress显示文章点击量
  • 室内设计效果图网站推荐在线玩网页游戏h5网站大全
  • C# 仿QQ聊天功能实现 (SQL Server数据库)
  • TensorFlow深度学习实战——节点分类
  • scipy的统计学库(4):用rv_histogram类实现随机抽样
  • Element Plus el-table 默认勾选行的方法
  • Linux系统函数opendir、closedir、readdir详解及案例(自定义ls工具)
  • 便捷网站建设哪家便宜网站建没有前景
  • 接口测试 | Postman的高级用法的测试使用
  • TR3--Transformer之pytorch复现
  • Traccar本地文件包含漏洞(CVE-2025-61666)
  • 建站网站推荐icp域名备案查询系统
  • 智能美颜引擎:美颜SDK如何实现自适应芯片性能优化
  • Java中的boolean与Boolean
  • Flutter高级进阶教程(视频教程)
  • Rocketmq 分布式事务 两阶段提交
  • 骑行,团骑和独骑冲突吗?