一、字符串中找出连续最长的数字串(双指针)
字符串中找出连续最长的数字串_牛客题霸_牛客网
#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%0
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;
}
// 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;//统计0
int 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;//记录最大利润 有可能是逆序的 所以结果就是0
for(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;
}