观前提醒:
笔试所有系列文章均是记录本人的笔试题思路与代码,从中得到的启发和从别人题解的学习到的地方,所以关于题目的解答,只是以本人能读懂为目标,如果大家觉得看不懂,那是正常的。如果对本文的某些知识有不同的观点,欢迎讨论。
题目链接:
第一题:登录—专业IT笔试面试备考平台_牛客网
第二题:登录—专业IT笔试面试备考平台_牛客网【重做】
第三题:【模板】拓扑排序_牛客题霸_牛客网【重做】
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第一题
思路:
一道很简单的数学题,我们可以直接模拟思路就好了。
方法一:正向计算
我们直接从i=1开始遍历观察,找到离目标值最近的两个值。
方法二:反向计算
我们直接将数字开方并且取整数部位,然后在得到的结果与结果+1的完全平方数当中考虑就好了。
代码:
//解法一
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<stdlib.h>
#include<string>
#include<vector>
using namespace std;int main()
{long long num=0;cin>>num;long long dp;long long i=0;for(;i*i<num;i++){dp=i*i;}if(abs(num-i*i)>abs(num-dp)){cout<<dp<<endl; }elsecout<<i*i<<endl;return 0;
}//解法二
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<stdlib.h>using namespace std;int main()
{long long num=0;cin>>num;long long x=(long long)sqrt(num);if(abs(num-x*x)>abs(num-(x+1)*(x+1))){cout<<(x+1)*(x+1)<<endl; }elsecout<<x*x<<endl;return 0;
}
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第二题
思路:
我们看完题目,我们可能有思路就是直接假设每个声调的人直接分组,但是这个思路的缺陷是很明显的,那就是复杂度太高了。既然这样那我们就正难则反,我们直接假设每个小组的最大人数,从1人开始到n人当中人数最多声调的人数,讨论只要有一次分法可以成功,我们就可以直接返回,返回答案。
优化解法:我们观察上面的暴力枚举我们可以发现暴力数组当中的规律,所以根据规律我们就可以将暴力枚举优化为二分。
代码:
#include<vector>
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<unordered_map>
#include<queue>
using namespace std;long long n=0,m=0;bool check(int x,unordered_map<long long,int> hash)
{int g=0;for(auto& [a,b]:hash){g+=b/x+(b%x == 0?0:1);}return g<=m;
}int main()
{cin>>n>>m;long long x=0;long long M=0;unordered_map<long long,int> hash;for(int i=0;i<n;i++){cin>>x;hash[x]++;if(hash[x] > M) M=hash[x];}if(hash.size() > m) {cout<<"-1"<<endl;return 0;}else{int left=1,right=M;while(left<right){int mid=(left+right)>>1;if(check(mid,hash)) right=mid;else left=mid+1;}cout<<left<<endl;}return 0;
}
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第三题
思路:
一道拓扑排序的模板题,直接模拟实现就好。
代码:
#include <iostream>
#include <vector>
#include <queue>
using namespace std;#define N 2e5+1
vector<vector<int>> edges(N);
vector<int> in(N); //表示入度信息int main() {vector<int> ret;int n=0,m=0;cin>>n>>m;for(int i=0;i<m;i++){int x=0,y=0;cin>>x>>y;edges[x].push_back(y);in[y]++;}queue<int> q;for(int i=1;i<=n;i++){if(in[i] == 0){q.push(i);}}while(!q.empty()){int x=q.front();ret.push_back(x);q.pop();for(auto b:edges[x]){in[b]--;if(in[b] == 0){q.push(b);}}}if(ret.size() == n) {for(int i=0;i<ret.size()-1;i++){cout<<ret[i]<<" ";}cout<<ret[n-1];}else{cout<<"-1"<<endl;}return 0;
}