笔试强训:Day7

一、旋转字符串(左旋字符串)

旋转字符串_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    bool solve(string A, string B) {
        if(A.size()!=B.size()) return false;
        return (A+A).find(B)!=-1;
    }
};

二、**合并k个已排序的链表(重写堆/归并排序)

合并k个已排序的链表_牛客题霸_牛客网

解法1:利用堆

cpp 复制代码
#include <queue>
class Solution {
public:
    struct cmp{
        bool operator()(ListNode*l1,ListNode*l2){//注意 小根堆是大于
            return l1->val>l2->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<ListNode*,vector<ListNode*>,cmp> heap;//小根堆
        for(auto&head:lists)
           if(head) heap.push(head);
        ListNode* newhead=new ListNode(0);//哨兵头节点
        ListNode*ptail=newhead;//用来尾插
        while(!heap.empty()){
            auto t=heap.top();
            heap.pop();
            ptail=ptail->next=t;
            if(t->next) heap.push(t->next);
        }
        ListNode*ret=newhead->next;
        delete newhead;
        return ret;
    }
};

解法2:利用归并排序(面试经典)

cpp 复制代码
class Solution {
public:
    //利用归并排序
    ListNode* mergeKLists(vector<ListNode*>&lists) {
        return mergesort(lists,0,lists.size()-1);
    }
    ListNode* mergesort(vector<ListNode*>&lists,int left,int right){
        if(left>right) return nullptr;
        else if(left==right) return lists[left];//只有一个的情况
        int mid=(left+right)>>1;
        ListNode*cur1=mergesort(lists,left,mid);
        ListNode*cur2=mergesort(lists,mid+1,right);
        //加一个哨兵头结点
        ListNode* newhead = new ListNode(0);
        ListNode* ptail=newhead;//用来尾插
        while(cur1&&cur2){
            if(cur1->val<=cur2->val){
                ptail->next=cur1;
                cur1=cur1->next;
            }
            else{
                ptail->next=cur2;
                cur2=cur2->next;
            }
            ptail=ptail->next;
        }
        //还有剩的就直接接在后面
        if(cur1) ptail->next=cur1;
        else ptail->next=cur2;
        ListNode*ret=newhead->next;
        delete newhead;
        return ret;
    }
};

三、滑雪(记忆化搜索)

滑雪_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
const int N=110;
int arr[N][N];
int memo[N][N];//记忆数组
int dx[4]={0,0,1,-1};
int dy[4]={-1,1,0,0};
int n,m;
int dfs(int i,int j){
    if(memo[i][j]) return memo[i][j];
    int ret=1;
    for(int k=0;k<4;++k){
        int x=dx[k]+i,y=dy[k]+j;
        if(x>=1&&x<=n&&y>=1&&y<=m&&arr[x][y]<arr[i][j])
        ret=max(ret,1+dfs(x,y));
    }
    return memo[i][j]=ret;
}
int main() {
   //严格单调递减
   cin>>n>>m;
   for(int i=1;i<=n;++i)
     for(int j=1;j<=m;++j) cin>>arr[i][j];
   int ret=1;
   for(int i=1;i<=n;++i)
     for(int j=1;j<=m;++j)
       ret=max(ret,dfs(i,j));
    cout<<ret<<endl;
}

四、天使果冻(递推)

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

直接用两个变量就行了

cpp 复制代码
#include<iostream>
using namespace std;
int n,q,x;
const int N=1e5+10;
int max1,max2;//前面是最大 后面是次大
int arr[N];
int main(){
    cin>>n;
    cin>>max1;
    for(int i=2;i<=n;++i){
        cin>>arr[i];
        if(arr[i]>=max1){
            max2=max1;
            max1=arr[i];
        }
        else if(arr[i]>max2) max2=arr[i];
        arr[i]=max2;
    }
    cin>>q;
    while(q--){
        cin>>x;
        cout<<arr[x]<<endl;
    }
}

五、**dd爱旋转(矩阵旋转规律+优化模拟)

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

如果每次都去尝试旋转遍历,那么时间复杂度是q*n^2

但是利用下面"消消乐"性质,时间复杂度就变成了q+n^2

cpp 复制代码
#include<iostream>
using namespace std;
int n,q,x;
const int N=1010;
int arr[N][N];
int row,col;//行变化和列变化的次数
void setrow(){//行变换
    for(int i=0;i<n/2;++i)
        for(int j=0;j<n;++j)
            swap(arr[i][j],arr[n-i-1][j]);
}
void setcol(){//列变换
   for(int i=0;i<n;++i)
        for(int j=0;j<n/2;++j)
            swap(arr[i][j],arr[i][n-j-1]);
}
int main(){
    cin>>n;
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j) cin>>arr[i][j];
    cin>>q;
    while(q--){
        cin>>x;
        if(x==1) ++col;
        ++row;
    }
    if(row%2) setrow();
    if(col%2) setcol();
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j)
            cout<<arr[i][j]<<" ";
        cout<<endl;
    }
}

六、**小红取数(01背包+同余定理)

小红取数_牛客题霸_牛客网

无法空间优化

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1010;
LL arr[N];
LL dp[N][N];//dp[i][j]表示从前i个人选 总和%k==j时的最大和是多少
int n,k;
int main() {
   cin>>n>>k;
   memset(dp, -0x3f, sizeof dp);
   dp[0][0] = 0;
   for(int i=1;i<=n;++i) cin>>arr[i];
   for(int i=1;i<=n;++i)
      for(int j=0;j<k;++j)
        dp[i][j]=max(dp[i-1][j],dp[i-1][(j-arr[i]%k+k)%k]+arr[i]);
   if(dp[n][0]<=0) cout<<-1<<endl;
   else cout<<dp[n][0]<<endl;
}

七、神奇的字母2(哈希)

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

cpp 复制代码
#include<iostream>
#include<string>
using namespace std;
string s;
int main(){
    int hash[26]={0};
    char ret=0;
    int maxcount=0;
    while(cin>>s)
        for(auto&ch:s)
            if(++hash[ch-'a']>maxcount){
                maxcount=hash[ch-'a'];
                ret=ch;
            }
    cout<<ret<<endl;
}

八、字符编码(哈夫曼编码)

字符编码_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;
string s;
int main() {
    while(cin>>s){
        //先统计每个字符的频次 然后再丢到小根堆里
        int hash[128]={0};
        for(auto&ch:s) ++hash[ch];
        //将频次丢到小根堆里
        priority_queue<int,vector<int>,greater<int>> heap;
        for(int i=0;i<128;++i) 
           if(hash[i]) heap.push(hash[i]);
        int ret=0;
        while(heap.size()>1){
            int t1=heap.top();
            heap.pop();
            int t2=heap.top();
            heap.pop();
            ret+=t1+t2;
            heap.push(t1+t2);
        }
        cout<<ret<<endl;
    }
}

九、最少的完全平方数(完全背包)

最少的完全平方数_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
//完全背包问题
int n;
const int N=1e4+10;
int dp[N];
int main() {
    cin>>n;
    memset(dp,0x3f,sizeof dp);
    dp[0]=0;
    for(int i=1;i*i<=n;++i)
       for(int j=i*i;j<=n;++j)
         dp[j]=min(dp[j],dp[j-i*i]+1);
    cout<<dp[n]<<endl;
}

十、*游游的字母串(优化枚举)

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

cpp 复制代码
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
string s;
int main(){
    cin>>s;
    int ret=0x3f3f3f3f;
    for(char i='a';i<='z';++i){
        int sum=0;//统计变化的次数
        for(auto&ch:s)
            sum+=min(abs(ch-i),26-abs(ch-i));
        ret=min(sum,ret);
    }
    cout<<ret<<endl;
}

十一、体育课测试2(拓扑排序)

体育课测验(二)_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    vector<int> findOrder(int numProject, vector<vector<int>>& groups) {
       vector<vector<int>> edges(numProject);//邻接表
       vector<int> in(numProject);//入度表
       vector<int> ret;//结果集
       ret.reserve(numProject);//提前扩容
       for(auto&v:groups){//开始建边  然后填入度表
          int a=v[0],b=v[1];
          edges[b].emplace_back(a);
          ++in[a];
       }
       //开始遍历入度表 然后把度为0的插入到队列中
       queue<int> q;
       for(int i=0;i<numProject;++i)
           if(!in[i]) q.emplace(i);
        //开始做事
        while(!q.empty()){
            int a=q.front();
            q.pop();
            ret.emplace_back(a);
            //把所有跟t有关的入度都--
            for(auto b:edges[a]) 
              if(--in[b]==0) q.emplace(b);
        }
        if(ret.size()==numProject) return ret;
        return {};
    }
};

十二、合唱队形(序列dp)

合唱队形_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
using namespace std;
const int N=1010;
int arr[N];//身高数组
int f[N],g[N];//最长递增子序列 
//f是从前往后 以i位置为结尾时的最长递增子序列
//g是从后往前  以i位置为结尾时的最长递增子序列
int n;
int main() {
   cin>>n;
   for(int i=1;i<=n;++i) cin>>arr[i];
   //从前往后
   for(int i=1;i<=n;++i){
      f[i]=1;
      for(int j=1;j<i;++j)
         if(arr[j]<arr[i]) f[i]=max(f[i],f[j]+1);
   }
   //从后往前
   for(int i=n;i>=1;--i){
      g[i]=1;
      for(int j=i+1;j<=n;++j)
         if(arr[j]<arr[i]) g[i]=max(g[i],g[j]+1);
   }
   int ret=1;
   for(int i=1;i<=n;++i)
       ret=max(ret,f[i]+g[i]-1);
    cout<<n-ret<<endl;
}

十三、棋子翻转(模拟)

棋子翻转_牛客题霸_牛客网

cpp 复制代码
class Solution {
public:
    int dx[4]={0,0,-1,1};
    int dy[4]={1,-1,0,0};
    vector<vector<int>> flipChess(vector<vector<int>>& A, vector<vector<int>>&f) {
        for(auto&v:f){
            int a=v[0]-1,b=v[1]-1;
            for(int k=0;k<4;++k){
                int x=dx[k]+a,y=dy[k]+b;
                if(x>=0&&x<4&&y>=0&&y<4) A[x][y]^=1;
            }
        }
        return A;
    }
};

十四、**宵暗的妖怪(类似打家劫舍实际不是)

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

cpp 复制代码
//打家劫舍问题 但是不能抢到最后一家
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL arr[N],dp[N];
//dp[i]表示1-i区间的最大饱食度是多少
//dp[i-3]+arr[i]
int n;
int main(){
    cin>>n;
    for(int i=1;i<=n;++i) cin>>arr[i];
    for(int i=3;i<=n;++i) 
        dp[i]=max(dp[i-1],dp[i-3]+arr[i-1]);
    cout<<dp[n]<<endl;
}

十五、**过桥(贪心+双指针+层序遍历思想)

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

cpp 复制代码
#include<iostream>
using namespace std;
int n;
int arr[2010];
int bfs(){
    int left=1,right=1,maxpos=1,ret=0;
    while(left<=right){
        if(maxpos>=n) return ret;
        for(int i=left;i<=right;++i)
            maxpos=max(maxpos,arr[i]+i);
        left=right+1;
        right=maxpos;
        ++ret;
    }
    return -1;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i) cin>>arr[i];
    cout<<bfs()<<endl;
}

十六、最大差值

最大差值_牛客题霸_牛客网

这题类似之前遇到的股票问题1

cpp 复制代码
class Solution {
public:
    int getDis(vector<int>& A, int n) {
       int ret=0;//记录最大差值
       int prevmin=A[0];//记录在这之前的最小值
       for(int i=1;i<n;++i){
          ret=max(ret,A[i]-prevmin);
          prevmin=min(prevmin,A[i]);
       }
       return ret;
    }
};

十七、兑换零钱(完全背包)

兑换零钱_牛客题霸_牛客网

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;
//dp[i][j]表示从前i个数选  面值恰好为j的最小张数
const int N=1010,M=5010;
int n,aim;
int arr[N],dp[M];
int main() {
    cin>>n>>aim;
    memset(dp,0x3f,sizeof dp);
    dp[0]=0;
    for(int i=1;i<=n;++i) cin>>arr[i];
    for(int i=1;i<=n;++i)
       for(int j=arr[i];j<=aim;++j)
          dp[j]=min(dp[j],dp[j-arr[i]]+1);
    if(dp[aim]>=0x3f3f3f3f) cout<<-1<<endl;
    else cout<<dp[aim]<<endl;
}

十八、**小红的子串(滑动窗口+前缀和)

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

cpp 复制代码
#include<string>
#include<iostream>
using namespace std;
typedef long long LL;
int n,l,r;
string s;
LL find(int x){//1-x个种类的数量 用滑动窗口
    if(x==0) return 0;
    LL ret=0;
    int hash[26]={0},kinds=0;
    //滑动窗口
    for(int left=0,right=0;right<n;++right){
        if(hash[s[right]-'a']++==0) ++kinds;
        while(kinds>x)
            if(--hash[s[left++]-'a']==0) --kinds;
        ret+=right-left+1;
    }
    return ret;
}
int main(){
    cin>>n>>l>>r>>s;
    cout<<find(r)-find(l-1)<<endl;
}
相关推荐
烨然若神人~3 分钟前
算法第38天|322.零钱兑换\139. 单词拆分
算法
Hat_man_36 分钟前
Windows下memcpy_s如何在Linux下使用
linux·c++
sukalot43 分钟前
window显示驱动开发—输出合并器阶段
驱动开发·算法
fei_sun1 小时前
【编译原理】语句的翻译
算法
Xの哲學1 小时前
hostapd 驱动注册机制深度分析
linux·网络·算法·wireless
老一岁2 小时前
c++set和pair的使用
开发语言·c++
int型码农2 小时前
数据结构第八章(六)-置换选择排序和最佳归并树
java·c语言·数据结构·算法·排序算法
@我漫长的孤独流浪2 小时前
数据结构----排序(3)
数据结构·c++·算法
oioihoii3 小时前
C++11 GC Interface:从入门到精通
java·jvm·c++
salsm3 小时前
Clang Static Analyzer 使用教程:本地 + CMake + GitHub Actions 自动静态分析实战
c++·静态分析·clang·代码质量