笔试强训:Day5

一、笨小猴(哈希+数学)

笨小猴_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
#include <cmath>
using namespace std;
string s;
bool isprime(int x){
    //试除法
    if(x==2) return true;
    if(x<2||x%2==0) return false;
    int n=sqrt(x);
    for(int i=3;i<=n;i+=2)
      if(x%i==0) return false;
    return true;
}
int main() {
    cin>>s;
    int hash[26]={0};//哈希表
    for(auto&ch:s) ++hash[ch-'a'];
    int maxn=0,minn=100;
    for(int i=0;i<26;++i)//找最大值和最小值
       if(hash[i]){
        maxn=max(maxn,hash[i]);
        minn=min(minn,hash[i]);
       }
    int x=maxn-minn;
    if(isprime(x)) {
        cout<<"Lucky Word"<<endl;
        cout<<x<<endl;
    }
    else {
        cout<<"No Answer"<<endl;
        cout<<0<<endl;
    }
   
}

二、主持人调度(左端点排序)

主持人调度(一)_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    bool hostschedule(vector<vector<int> >& schedule) {
       sort(schedule.begin(),schedule.end());
       int n=schedule.size();
       for(int i=0;i<n-1;++i)
         if(schedule[i][1]>schedule[i+1][0]) return false;
       return true;
    }
};

三、分割等和子集(01背包)

分割等和子集_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
//从数组中挑选一些数字 是否可以恰好等于sum/2  01背包问题
int n;
const int N=505,M=505*105/2;
int arr[N];
bool dp[M];
int main(){
  cin>>n;
  int sum=0;//记录总和
  for(int i=1;i<=n;++i){
    cin>>arr[i];
    sum+=arr[i];
  }
  if(sum%2) cout<<"false"<<endl;//不能整除
  else{
    sum/=2;
    dp[0]=true;
    for(int i=1;i<=n;++i)
      for(int j=sum;j>=arr[i];--j)
         dp[j]=dp[j]||dp[j-arr[i]];
    if(dp[sum]) cout<<"true"<<endl;
    else cout<<"false"<<endl;
  }
}

四、小红的ABC(找规律)

登录---专业IT笔试面试备考平台_牛客网

cpp 复制代码
//a b c三个字母 最短的 那么只有可能是2和3
#include<iostream>
#include<string>
using namespace std;
string s;
int main(){
    cin>>s;
    int n=s.size();
    int ret=-1;//没有回文串的情况
    for(int i=0;i<n-1;++i){
        if(s[i]==s[i+1]){
            ret=2;
            break;
        }
        if(i+2<n&&s[i]==s[i+2]) ret=3;
    }
    cout<<ret<<endl;
}

五、不相邻取数(状态dp)

不相邻取数_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
const int N=2e5+10;
int n;
int arr[N],f[N],g[N];//f[i]是选了i位置后的最大  g[i]是没选i位置后的最大
int main() {
   cin>>n;
   for(int i=1;i<=n;++i) cin>>arr[i];
   for(int i=1;i<=n;++i){
     f[i]=g[i-1]+arr[i];
     g[i]=max(f[i-1],g[i-1]);
   }
   cout<<max(f[n],g[n])<<endl;
}

六、**空调遥控(排序+二分/滑动窗口)

登录---专业IT笔试面试备考平台_牛客网

解法1:排序+二分找区间(左端点+右端点组合)

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int arr[N];
int n,p;
int main(){
    cin>>n>>p;
    for(int i=0;i<n;++i) cin>>arr[i];
    sort(arr,arr+n);
    int ret=1;
    //开始枚举
    for(int i=arr[0];i<=arr[n-1];++i){//枚举温度
        int left=0,right=n-1;
        while(left<right){//begin-2 用左端点区间
            int mid=left+(right-left)/2;
            if(arr[mid]<i-p) left=mid+1;
            else right=mid;
        }
       int begin=left;
       right=n-1;//left可以继续从原来的位置找 重置right就行了
       while(left<right){//begin-p 用右端点区间
            int mid=left+(right-left+1)/2;
            if(arr[mid]<=i+p) left=mid;
            else right=mid-1;
        }
       ret=max(ret,right-begin+1);
    }
    cout<<ret<<endl;
    return 0;
}

解法2:滑动窗口

cpp 复制代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int arr[N];
int n,p;
int main(){
    cin>>n>>p;
    p*=2;//差值
    for(int i=0;i<n;++i) cin>>arr[i];
    sort(arr,arr+n);
    //滑动窗口 差值在2*p的最大区间
    int ret=1;
    for(int left=0,right=0;right<n;++right){
        while(arr[right]-arr[left]>p)++left;
        ret=max(ret,right-left+1);
    }
    cout<<ret<<endl;
}

七、kotori和气球(组合数学)

登录---专业IT笔试面试备考平台_牛客网

cpp 复制代码
#include<iostream>
using namespace std;
const int mod=109;
int n,m;
int main(){
    cin>>n>>m;
    //n与m个(n-1)的乘积
    int ret=n;
    for(int i=0;i<m-1;++i) ret=ret*(n-1)%mod;
    cout<<ret<<endl;
}

八、 *走迷宫(单源最短路BFS)

走迷宫_牛客题霸_牛客网

单源最短路问题:

cpp 复制代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N=1010;
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
int n,m,x1,x2,y1,y2;
char arr[N][N];
int dis[N][N];//不仅用来看看搜索过了没 
//单源最短路问题 用bfs扩展
int bfs(){//-1表示走不到
   if(arr[x2][y2]=='*') return -1;
   memset(dis, -1, sizeof dis); // 表⽰还没开始搜索
   queue<pair<int,int>> q;
   q.emplace(x1,y1);
   dis[x1][y1]=0;
   while(!q.empty()){
       auto[a,b]=q.front();
       q.pop();
       for(int k=0;k<4;++k){
        int x=dx[k]+a,y=dy[k]+b;
        if(x>=1&&x<=n&&y>=1&&y<=m&&arr[x][y]=='.'&&dis[x][y]==-1){
            q.emplace(x,y);
            dis[x][y]=dis[a][b]+1;
            if(x==x2&&y==y2) return dis[x][y];
        }
       }
   }
   return -1;
}
int main() {
   cin>>n>>m>>x1>>y1>>x2>>y2;
   for(int i=1;i<=n;++i)
       for(int j=1;j<=m;++j) cin>>arr[i][j];
   cout<<bfs()<<endl;
}

1、读取定长字符串也可以按照字符一个个读取

2、单源最短路的标记数组不仅可以记录距离,也可以用来标记是否搜索过

3、memset用来标记-1

九、**主持人调度2(贪心+优先级队列+左端点排序)

主持人调度(二)_牛客题霸_牛客网

解法1:贪心+优先级队列+左端点排序

cpp 复制代码
class Solution {
public:
    int minmumNumberOfHost(int n, vector<vector<int>>& startEnd) {
       sort(startEnd.begin(),startEnd.end());
       priority_queue<int,vector<int>,greater<int>> heap;//创建一个小根堆
       heap.push(startEnd[0][1]);
       for(int i=1;i<n;++i){
        int a=startEnd[i][0],b=startEnd[i][1];
        if(a>=heap.top()) heap.pop(); //说明没有重叠
        heap.push(b);
       }
       return heap.size();
    }
};

解法2:分别排序+遍历比较

cpp 复制代码
class Solution {
public:
    int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
        vector<int> start;
        vector<int> end;
        //分别得到活动起始时间
        for(int i = 0; i < n; i++){
            start.push_back(startEnd[i][0]);
            end.push_back(startEnd[i][1]);
        }
        //分别对开始和结束时间排序
        sort(start.begin(), start.end());
        sort(end.begin(), end.end());
        int res = 0;
        int j = 0;//遍历结束时间
        for(int i = 0; i < n; i++)
            //新开始的节目大于上一轮结束的时间,主持人不变
            if(start[i] >= end[j])  j++;  
            else res++;  //主持人增加
        return res;
    }
};

十、游游的重组偶数(数学)

游游的重组偶数__牛客网

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
//把每个数字中为偶数的部分放到最后就可以了
int q;
string s;
int main() {
    cin>>q;
    while(q--){
        cin>>s;
        int n=s.size();
        int i=n-1;
        for(;i>=0;--i)
           if(s[i]%2==0){
            swap(s[i],s[n-1]);
            break;
           }
        if(i!=-1) cout<<s<<endl;
        else cout<<-1<<endl;
    }
}

十一、**体操队形(枚举+dfs)

登录---专业IT笔试面试备考平台_牛客网

cpp 复制代码
#include<iostream>
using namespace std;
int n;
int ret=0;//统计最终结果
const int N=11;
int arr[N];
bool vis[N];//队员
void dfs(int pos){
    if(pos==n+1){
        ++ret;
        return;
    }//说明找到了一种合法方案
    //开始一个个位置去选择
    for(int i=1;i<=n;++i){
        if(vis[i]) continue;//如果该位置的人选过了 就跳过
        //我不可能排在我想排的人前面 那后面再怎么选都是错的
        if(vis[arr[i]]) return;
        vis[i]=true;
        dfs(pos+1);
        vis[i]=false;
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i) cin>>arr[i];
    dfs(1);//从第一个位置开始选
    cout<<ret<<endl;
}

十二、**二叉树中的最大路径和(dfs+树形dp思想)

二叉树中的最大路径和_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    int ret=-1010;//统计最大值
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return ret;
    }
    int dfs(TreeNode* root){
        if(root==nullptr) return 0;
        int left=max(dfs(root->left),0);//最大左子链
        int right=max(dfs(root->right),0);//最大右子链
        ret=max(ret,left+right+root->val);//经过root的最大路径
        return root->val+max(left,right);//给上层返回单链的信息
    }
};

十三、*排序子序列(模拟+贪心)

排序子序列_牛客笔试题_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
int n;
const int N=1e5+10;
int arr[N];
int main() {
  cin>>n;
  for(int i=0;i<n;++i) cin>>arr[i];
  int ret=0,i=0;
  while(i<n){
    if(i==n-1){//这个时候不存在后面的数比了 所以自己就是一个子序列
        ++ret;
        break;
    }
    if(arr[i+1]>arr[i]){//搞一个上升的子序列
       while(i+1<n&&arr[i+1]>=arr[i]) ++i;
       ++ret;
    }
    else if(arr[i+1]<arr[i]){//说明搞一个下降的子序列
       while(i+1<n&&arr[i+1]<=arr[i]) ++i;
       ++ret;
    }
    else  while(i+1<n&&arr[i+1]==arr[i]) ++i;
    ++i;
  }
  cout<<ret<<endl;
}

十四、消减整数(贪心+数学)

登录---专业IT笔试面试备考平台_牛客网

cpp 复制代码
#include<iostream>
using namespace std;
//得确保 正好a*2==cur 才可以翻倍
int t,h;
int main(){
    cin>>t;
    while(t--){
        cin>>h;
        int a=1,ret=0;
        while(h){
            h-=a;
            ++ret;
            if(h%(a*2)==0) a*=2;
        }
        cout<<ret<<endl;
    }
}

十五、最长上升子序列2(贪心+二分)

最长上升子序列(二)_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    int LIS(vector<int>&nums) {
       int n=nums.size();
       if(n<=1) return n;
       //至少有两个元素
       vector<int> v;//用来当数组
       v.emplace_back(nums[0]);
       for(int i=1;i<n;++i){
           int x=nums[i];
           //如果比后面的大 就直接插入
           if(x>v.back()) v.emplace_back(nums[i]);
           else if(x==v.back()) continue;
           else{//二分查找插入的位置
              int left=0,right=v.size()-1;
              while(left<right){
                int mid=left+(right-left)/2;
                if(v[mid]<x) left=mid+1;
                else right=mid;
              }
              v[left]=x;
           }
       } 
       return v.size();
    }
};

十六、爱吃素(数学)

登录---专业IT笔试面试备考平台_牛客网

cpp 复制代码
#include<iostream>
#include<cmath>
using namespace std;
int t;
typedef long long LL;
LL a,b;
bool isprim(LL x){
    if(x==2) return true;
    if(x<2||x%2==0) return false;
    int n=sqrt(x);
    for(int i=3;i<=n;i+=2)
        if(x%i==0) return false;
    return true;
}
int main(){
    cin>>t;
    while(t--){
        cin>>a>>b;
        if((a==1&&isprim(b))||(b==1&&isprim(a))) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

十七、相差不超过k的最多数(排序+滑动窗口)

相差不超过k的最多数_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;
int n,k;
const int N=2e5+1;
int arr[N];
int main() {
   cin>>n>>k;
   for(int i=0;i<n;++i) cin>>arr[i];
   sort(arr,arr+n);
   int ret=1;
   for(int left=0,right=0;right<n;++right){
      while(arr[right]-arr[left]>k) ++left;
      ret=max(right-left+1,ret);
   }
   cout<<ret<<endl;
}

十八、最长公共子序列1(LCSdp)

最长公共子序列(一)_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
const int N=1010;
char s1[N],s2[N];
int dp[N][N];
int n,m;
int main() {
   //dp[i][j]表示以0-i的字符串1中 与0-j字符串2中 的最长公共子序列长度
   cin>>n>>m;
   for(int i=1;i<=n;++i) cin>>s1[i];
   for(int i=1;i<=m;++i) cin>>s2[i];
   //开始进行dp
   for(int i=1;i<=n;++i)
     for(int j=1;j<=m;++j)
       if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1;
       else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
   cout<<dp[n][m]<<endl;
}
相关推荐
Echo``6 分钟前
1:OpenCV—图像基础
c++·图像处理·人工智能·opencv·算法·计算机视觉·视觉检测
ALex_zry37 分钟前
Ubuntu 20.04 C++开发环境搭建指南(2025版)
linux·c++·ubuntu
COOCC11 小时前
激活函数全解析:定义、分类与 17 种常用函数详解
人工智能·深度学习·神经网络·算法·机器学习·计算机视觉·自然语言处理
林下清风~1 小时前
力扣hot100——347.前K个高频元素(cpp手撕堆)
算法·leetcode·职场和发展
进击的小白菜2 小时前
Java回溯算法解决非递减子序列问题(LeetCode 491)的深度解析
java·算法·leetcode
-一杯为品-3 小时前
【深度学习】#11 优化算法
人工智能·深度学习·算法
_F_y3 小时前
list简单模拟实现
c++·list
前进的程序员3 小时前
C++ 在 Windows 和 Linux 平台上的开发差异及常见问题
linux·c++·windows
-qOVOp-3 小时前
zst-2001 上午题-历年真题 计算机网络(16个内容)
网络·计算机网络·算法
Swift社区3 小时前
涂色不踩雷:如何优雅解决 LeetCode 栅栏涂色问题
算法·leetcode·职场和发展