【美团&字节】四道编程题(含思路)2020/09/06

备战秋招面试 微信搜索公众号【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. 动态规划。分别计算最后跳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';
}
  1. 两次单调栈。
#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';
}
  1. 最大子段和。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,分别讨论当前位置差分结果为-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';
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值