备战秋招面试 微信搜索公众号【TechGuide】关注更多新鲜好文和互联网大厂的笔经面经。
作者@TechGuide
点赞再看,养成习惯,您动动手指对原创作者意义非凡🤝
美团笔试
第一题
给出A,B两国想要的土地,输出只有A国想要的土地数,只有B国想要的土地数,两个国家都想要的土地数。
思路:简单的求交集大小,甚至不用给出交集,先遍历A,用set存下来,再遍历B,遇到set中有的就cnt++,最后输出A-cnt, B-cnt, cnt。
作者:js8544
链接:https://www.nowcoder.com/discuss/500649
来源:牛客网
int n, p, q;
set<int> a;
void solve() {
cin >> n >> p >> q;
for (int i = 0; i < p; i++) {
int x;
cin >> x;
a.insert(x);
}
int cnt = 0;
for (int i = 0; i < q; i++) {
int x;
cin >> x;
if (a.count(x)) cnt++;
}
cout<<p - cnt<<" "<<q - cnt<<" "<<cnt<<endl;
}
第二题,
给一串偶数个字符,只有大小写字母,求修改多少个字母可以让大小写数量相同。
思路:求出大小写个数,相减除以二即可。用islower判断大小写。
int n;
void solve() {
char c;
int l = 0, u = 0;
while (cin >> c) {
if (islower(c)) {
l++;
} else {
u++;
}
}
cout<<abs(l - u) / 2<<endl;
}
第三题
思路:观察到异或的两个性质:1. 可交换 2. 任何数异或自身为零。观察到mod的一个性质:循环。因此我们可以竖着求,而不是横着求。也就是我们遍历j去求,而不是i。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] pre = new int[n+1];
pre[0] = 0;
int res = 0;
for (int i = 1; i < n+1; i++) {
pre[i] = pre[i-1]^i;
}
for (int i = 1; i < n+1; i++) {
res = res^pre[n%i];
if((n/i)%2==1) res = res^pre[i-1];
}
for (int i = 0; i < n; i++) {
int a = sc.nextInt();
res = res^a;
}
System.out.println(res);
}
}
int n;
int pre[100001];
void solve() {
cin >> n;
pre[0] = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] ^ i;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
ans ^= pre[n % i];
if ((n / i) % 2) {
ans ^= pre[i - 1];
}
}
for (int i = 0; i < n; i++) {
int x;
cin >> x;
ans ^= x;
}
cout << ans << endl;
}
第四题
方法一:
作者:阿康201903182006590
链接:https://www.nowcoder.com/discuss/500551?type=6&channel=666&source_id=discuss_center_discuss_hot
来源:牛客网
import java.util.Scanner;
public class Main4 {
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
while(in.hasNext()){
int n=in.nextInt();
boolean flag=false;
int[] arr=new int[n];
for(int i=0;i<n;i++){
arr[i]=in.nextInt();
}
int empcnt=0;
for(int a:arr){
if(n==2&&a==2){
flag=false;
}
if(a==1){
empcnt++;
}else{
if(a==empcnt+1&&a>2&&a==n){
flag=true;
}
}
}
if(flag==true){
System.out.println("YES");
}else {
System.out.println("NO");
}
}
}
}
方法二:
int n;
int arr[25];
int child[25];
bool dfs(int x, set<int>& can) {
if (x == n) {
for (int i = 0; i < n; i++) {
if (arr[i] != 1 || child[i] == 1) return false;
}
return true;
}
set<int> new_can = can;
if (arr[x] != 1) new_can.insert(x);
for (int i : can) {
if (arr[i] > arr[x]) {
if (arr[i] == arr[x] + 1 && child[i] == 0) continue;
arr[i] -= arr[x];
child[i]++;
if (arr[i] == 1) new_can.erase(i);
if (dfs(x + 1, new_can)) return true;
if (arr[i] == 1) new_can.insert(i);
arr[i] += arr[x];
child[i]--;
}
}
return false;
}
void solve() {
bool flag = true;
REP(i, n) {
cin >> arr[i];
if (arr[i] == 2) {
flag = false;
}
}
if (!flag) {
cout << "NO" << endl;
return;
}
sort(arr, arr + n, greater<int>());
if (arr[0] != n) {
cout << "NO" << endl;
return;
}
set<int> can;
can.insert(0);
memset(child, 0, sizeof(child));
if (dfs(1, can)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
第五题
在这里插入代码片
牛客美团2020年校招真题解7:
打车派单场景, 假定有N个订单, 待分配给N个司机。每个订单在匹配司机前,会对候选司机进行打分,打分的结果保存在N*N的矩阵A, 其中Aij 代表订单i司机j匹配的分值。
假定每个订单只能派给一位司机,司机只能分配到一个订单。求最终的派单结果,使得匹配的订单和司机的分值累加起来最大,并且所有订单得到分配。
import java.util.*;
public class Main {
static double total = Integer.MIN_VALUE;
static List<List<Integer>> res;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
sc.nextLine();
double[][] scores = new double[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
scores[i][j] = sc.nextDouble();
}
sc.nextLine();
}
boolean[] vis = new boolean[N];
dfs(0, N,scores,new ArrayList<>(),0, vis);
System.out.println(total);
for (int i = 0; i < res.size() ; i++) {
for(int e:res.get(i)){
System.out.print(e+1);
System.out.print(" ");
}
System.out.println();
}
}
public static void dfs(int x, int n, double[][] scores, List<List<Integer>> temp, double sum, boolean[] vis){
if(x<0 || x>n) return;
// System.out.println("x:"+x);
// System.out.println("sum:"+sum);
if(x==n && sum>total){
res = new ArrayList<>(temp);
total = sum;
return;
}
for (int i = 0; i < n; i++) {
if(!vis[i]){
temp.add(Arrays.asList(x,i));
vis[i] = true;
dfs(x+1, n, scores, temp, sum+scores[x][i], vis);
vis[i] = false;
temp.remove(temp.size()-1);
}
}
}
}
牛客美团2020年校招真题解8:
2110年美团外卖火星第3000号配送站点有26名骑手,分别以大写字母A-Z命名,因此可以称呼这些骑手为黄家骑士特工A,黄家骑士特工B…黄家骑士特工Z,某美团黑珍珠餐厅的外卖流水线上会顺序产出一组包裹,美团配送调度引擎已经将包裹分配到骑手,并在包裹上粘贴好骑手名称,如RETTEBTAE代表一组流水线包裹共9个,同时分配给了名字为A B E R T的5名骑手。请在不打乱流水线产出顺序的情况下,把这组包裹划分为尽可能多的片段,同一个骑手只会出现在其中的一个片段,返回一个表示每个包裹片段的长度的列表。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
String s=scanner.nextLine();
int i=0,j=0,len=s.length();
while(j<len){
char c=s.charAt(j);
int tail=s.lastIndexOf(c);
int pre = j;
int temp = tail;
for (int k = j+1; k < temp; k++) {
tail = Math.max(tail, s.lastIndexOf(s.charAt(k)));
j = tail;
}
j++;
System.out.print(j-pre+" ");
}
}
}
字节
第一题
- 动态规划。分别计算最后跳1步和跳2步的状态
作者:yuzining
链接:https://www.nowcoder.com/discuss/500713?type=2
来源:牛客网
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
vector<vector<int64_t>> dp(105, vector<int64_t>(2, 0));
dp[0][0] = 1;
for (int i = 1; i < 105; i++) {
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
if (i >= 2) {
dp[i][1] = dp[i - 2][0];
}
}
int n; cin >> n;
if (n == 0) {
cout << 0 << '\n';
return 0;
}
cout << (dp[n][0] + dp[n][1]) << '\n';
}
- 两次单调栈。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n; cin >> n;
int64_t ans = 0;
vector<int> a(n), l(n, 0);
stack<int> stk;
for (int i = 0; i < n; i++) {
cin >> a[i];
while (!stk.empty() && a[stk.top()] <= a[i]) {
stk.pop();
}
if (!stk.empty()) {
l[i] = stk.top() + 1;
}
stk.push(i);
}
while (!stk.empty()) {
stk.pop();
}
for (int i = n - 1; i >= 0; i--) {
while (!stk.empty() && a[stk.top()] <= a[i]) {
stk.pop();
}
if (!stk.empty()) {
ans = max(ans, (int64_t)(1ll * l[i] * (stk.top() + 1)));
}
stk.push(i);
}
cout << ans << '\n';
}
- 最大子段和。M=1,2直接做;当M>2时,先做两段,如果整段之和大于0,最优解要再加上中间(m-2)段的和
java实现:
作者:OFFER—PLSxD
链接:https://www.nowcoder.com/discuss/500713?type=2
来源:牛客网
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int [] arr = new int [n];
int [] L = new int [n]; // L[i] = first j satisfy arr[ j -1 ] > arr[i]
for(int i=0 ; i< n ; i++ ){
arr[i] = sc.nextInt();
}
Deque<Integer> s1 = new LinkedList<>(); // montonic decreasing stack
for(int i = n - 1 ; i >= 0 ; i-- ){
while(!s1.isEmpty() && arr[s1.peek()] < arr[i]){
L[s1.pop()] = i + 1 ; // idx start from 1
}
s1.push(i);
}
long max = 0L;
s1 = new LinkedList<>(); // montonic decreasing stack
for(int i = 0 ; i < n ; i++ ){
while(!s1.isEmpty() && arr[s1.peek()] < arr[i]){
int RR = (i + 1);// idx start from 1
int LL = L[s1.pop()];
max = Math.max ( max , 1L *LL * RR ) ;
}
s1.push(i);
}
System.out.println(max);
}
}
C++实现:
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m; cin >> n >> m;
vector<int> a(n * 2);
int64_t ans = LLONG_MIN, dp = 0, sum = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (dp <= 0) {
dp = a[i];
} else {
dp += a[i];
}
ans = max(ans, dp);
sum += a[i];
}
if (m == 1) {
cout << ans << '\n';
return 0;
}
int64_t link = LLONG_MIN;
for (int i = n; i < 2 * n; i++) {
a[i] = a[i - n];
if (dp <= 0) {
dp = a[i];
} else {
dp += a[i];
}
link = max(link, dp);
}
if (sum > 0) {
link += 1ll * sum * (m - 2);
}
cout << max(link, ans) << '\n';
}
- 差分数组,记录到当前位置上有多少个-1,分别讨论当前位置差分结果为-1,0,1的情况,递推更新答案。要用long long存。
#include <bits/stdc++.h>
using namespace std;
int a[100005], b[100005];
const int64_t MOD = 1e9 + 7;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, w; cin >> n >> w;
bool ok = true;
for (int i = 1; i <= n; i++) {
cin >> a[i];
a[i] = w - a[i];
b[i] = a[i] - a[i - 1];
if (a[i] < 0 || b[i] < -1 || b[i] > 1) {
ok = false;
}
}
b[n + 1] = -a[n];
if (b[n + 1] < -1 || b[n + 1] > 1) {
ok = false;
}
if (!ok) {
cout << "0\n";
return 0;
}
int64_t ans = 1;
for (int i = 1; i <= n + 1; i++) {
if (b[i] == 0 || b[i] == -1) {
ans = (ans * (a[i] + 1)) % MOD;
}
}
cout << ans << '\n';
}