一、字符串中找出连续最长的数字串(双指针)
字符串中找出连续最长的数字串_牛客题霸_牛客网
#include <iostream>
#include <string>
#include <cctype>
using namespace std;int main() {//双指针string str;cin>>str;int n=str.size();int begin=-1,len=0;for(int left=0;left<n;++left)if(isdigit(str[left])){//如果left是数字的话int right=left;while(right<n&&isdigit(str[right])) ++right;//走到这说明right在结尾的下一个位置if(right-left>len){begin=left;len=right-left;}left=right;//再++left 没事 因为该位置一定不是数字 可以跳过}if(begin==-1) cout<<""<<endl;else cout<<str.substr(begin,len)<<endl;
}
// 64 位输出请用 printf("%lld")
二、岛屿数量(bfs/dfs)
岛屿数量_牛客题霸_牛客网
class Solution {
public:int m,n;int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};int solve(vector<vector<char>>& grid) {m=grid.size(),n=grid[0].size();int ret=0;for(int i=0;i<m;++i)for(int j=0;j<n;++j)if(grid[i][j]=='1'){++ret;//说明找到了一个岛屿dfs(grid,i,j);}return ret;}void dfs(vector<vector<char>>& grid,int i,int j){grid[i][j]='0';for(int k=0;k<4;++k){int x=dx[k]+i,y=dy[k]+j;if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]=='1') dfs(grid,x,y);}}
};
三、**拼三角(优化枚举)
登录—专业IT笔试面试备考平台_牛客网
#include<iostream>
#include<algorithm>//算法头文件 记得会拼
//优化后的枚举 只需要考虑4种情况
//012-345 023-145 034-125 045-123
int a[6];
using namespace std;
int main(){int t;cin>>t;while(t--){for(int i=0;i<6;++i) cin>>a[i];sort(a,a+6);//静态数组的用法if(a[0]+a[1]>a[2]&&a[3]+a[4]>a[5]||a[0]+a[2]>a[3]&&a[1]+a[4]>a[5]||a[0]+a[3]>a[4]&&a[1]+a[2]>a[5]||a[0]+a[4]>a[5]&&a[1]+a[2]>a[3]) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
}
四、**最小公倍数&最大公约数(数学)
求最小公倍数_牛客题霸_牛客网
#include <iostream>
using namespace std;
int gcd(int a,int b){//32%26=6 26%6=2 6%2=0 2%0if(b==0) return a;return gcd(b,a%b);
}
int main() {int a,b;cin>>a>>b;cout<<(a*b/gcd(a,b))<<endl;
}
// 64 位输出请用 printf("%lld")
五、**数组中的最长连续子序列(排序+双指针)
数组中的最长连续子序列_牛客题霸_牛客网
class Solution {
public:
//可以直接排序 但是要处理 值相等的情况 1 1 2 3 4 5 5 5 5 6 int MLS(vector<int>&nums) {int n=nums.size();sort(nums.begin(),nums.end());int ret=1;//双指针 我可以先找到第一个比前面大1的那个数for(int left=0;left<n;){int right=left+1,count=1;//while(right<n){if(nums[right-1]+1==nums[right]){++count;++right;}else if(nums[right-1]==nums[right]) ++right;else break;}ret=max(ret,count);left=right;}return ret;}
};
六、字母搜集(路径dp)
字母收集_牛客题霸_牛客网
#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;
}
// 64 位输出请用 printf("%lld")
七、添加逗号(模拟)
添加逗号_牛客题霸_牛客网
#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;
}
// 64 位输出请用 printf("%lld")
八、跳台阶(线性dp)
跳台阶_牛客题霸_牛客网
#include <iostream>
using namespace std;int main() {int n;cin>>n;if(n<=2) cout<<n<<endl;else{int a=1,b=2,c; //dp[1]=1 dp[2]=2 dp[3]=dp[1]+dp[2];for(int i=3;i<=n;++i){c=a+b;a=b;b=c;}cout<<c<<endl;}
}
九、**扑克牌顺子(排序/位图+模拟)
扑克牌顺子_牛客题霸_牛客网
解法1:排序+模拟
class Solution {
public:bool IsContinuous(vector<int>& nums) {//要对数组排序 同时统计0的个数 若相邻数字的空缺总数<=0的个数 那就是连续的sort(nums.begin(),nums.end());int zero=0;//统计0int i=0;while(nums[i]==0){++zero;++i;}int dis=0;//统计距离//记录五张牌中最大值max到最小值min的距离for(;i<4;++i){if(nums[i]==nums[i+1]) return false;dis+=nums[i+1]-nums[i]-1;}if(zero>=dis) return true;return false;}
};
解法2:找规律+位图
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;}
};
十、**最长回文子串(动归/马拉松/中心扩展)
最长回文子串_牛客题霸_牛客网
class Solution {
public:
//中心扩展算法int getLongestPalindrome(string A) {int n=A.size();int ret=1;for(int i=1;i<n;++i){//当长度是奇数的时候int left=i-1,right=i+1;while(left>=0&&right<n&&A[left]==A[right]){--left;++right;}ret=max(ret,right-left-1);//当长度是偶数的时候left=i-1,right=i;while(left>=0&&right<n&&A[left]==A[right]){--left;++right;}ret=max(ret,right-left-1);}return ret;}
};
十一、买卖股票的最好时机1(贪心)
买卖股票的最好时机(一)_牛客题霸_牛客网
#include <iostream>
using namespace std;
const int N=1e5+1;
int a[N];
int main() {int n;cin>>n;for(int i=0;i<n;++i) cin>>a[i];int prevmin=a[0];//记录前面的最小值int ret=0;//记录最大利润 有可能是逆序的 所以结果就是0for(int i=1;i<n;++i){ret=max(ret,a[i]-prevmin);prevmin=min(prevmin,a[i]);}cout<<ret<<endl;
}
// 64 位输出请用 printf("%lld")
十二、**过河卒(路径dp)
[NOIP2002 普及组] 过河卒_牛客题霸_牛客网
#include <iostream>
#include <cmath>
using namespace std;
long long dp[22][22];
int main() {int n,m,x,y;cin>>n>>m>>x>>y;x+=1,y+=1;//因为有虚拟节点dp[0][1]=1;for(int i=1;i<=n+1;++i)for(int j=1;j<=m+1;++j)if(i!=x&&j!=y&&abs(i-x)+abs(j-y)==3||i==x&&j==y) dp[i][j]=0;else dp[i][j]=dp[i-1][j]+dp[i][j-1];cout<<dp[n+1][m+1]<<endl;
}
// 64 位输出请用 printf("%lld")
十三、**游游的水果大礼包(枚举)
登录—专业IT笔试面试备考平台_牛客网
//一般来说枚举有三种方法
//1、选几个就用几个for循环 如果选超过3个以上的基本不适用
//2、用dfs把位置摆出来 然后尝试去填
//3、根据某些特性优化枚举 或者数量少的直接用if else
#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;
}
十四、**买卖股票的最好时机2(贪心/双指针)
买卖股票的最好时机(二)_牛客题霸_牛客网
解法1:双指针
#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")
解法2:贪心:把交易拆成一天一天
#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")
十五、倒置字符串(双指针)
倒置字符串_牛客题霸_牛客网
#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")
十六、删除公共字符(哈希)
删除公共字符_牛客题霸_牛客网
#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<<endl;
}
// 64 位输出请用 printf("%lld")
十七、**两个链表的第一个公共结点(模拟)
两个链表的第一个公共结点_牛客题霸_牛客网
解法1:计数 然后让长的先走 然后再一起走
class Solution {public:ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {if (!pHead1 || !pHead2) return nullptr;if(pHead1==pHead2) return pHead1;ListNode*cur1=pHead1,*cur2=pHead2;int a=0,b=0;while(cur1){cur1=cur1->next;++a;}while(cur2){cur2=cur2->next;++b;}//长的先走count2-count1步cur1=pHead1,cur2=pHead2;int m=a>b?b:a;while(a-m){cur1=cur1->next;--a;}while(b-m){cur2=cur2->next;b--;}while(cur1!=cur2){cur1=cur1->next;cur2=cur2->next;}return cur1;}
};
解法2:等价关系(数学特性)
class Solution {public:ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {if (!pHead1 || !pHead2) return nullptr;if(pHead1==pHead2) return pHead1;ListNode*cur1=pHead1,*cur2=pHead2;while(cur1!=cur2){cur1=cur1?cur1->next:pHead2;cur2=cur2?cur2->next:pHead1;}return cur1;}
};
解法3:借助set
class Solution {public:ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {if (!pHead1 || !pHead2) return nullptr;if(pHead1==pHead2) return pHead1;unordered_set<ListNode*> s;while(pHead1){s.insert(pHead1);pHead1=pHead1->next;}while(pHead2){if(s.count(pHead2)) return pHead2;pHead2=pHead2->next;}return nullptr;}
};
十八、**mari和shiny(状态dp+优化)
登录—专业IT笔试面试备考平台_牛客网
#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;
}