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

美团笔试

第一题

给出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。

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;
  }
}

字节

第一题

  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';
}

猜你喜欢

转载自blog.csdn.net/weixin_41896265/article/details/108435552
今日推荐