美团笔试
一共5道题目, 编程题目 , 全部AC , 第四题卡了好久… 左思右想… 我觉得暴力过不了的= = 是在没办法了 暴力…
这样本有点水的…没想到过了…
来看题目
第一题
题目概要
小团深谙保密工作的重要性,因此在某些明文的传输中会使用一种加密策略,
小团如果需要传输一个字符串S,则他会为这个字符串添加一个头部字符串和一个尾部字符串。
头部字符串满足至少包含一个“MT”子序列,且以T结尾。尾部字符串需要满足至少包含一个“MT”子序列,且以M开头。
例如AAAMT和MAAAT都是一个合法的头部字符串,而MTAAA就不是合法的头部字符串。
很显然这样的头尾字符串并不一定是唯一的,因此我们还有一个约束,就是S是满足头尾字符串合法的情况下的最长的字符串。
很显然这样的加密策略是支持解码的,给出你一个加密后的字符串,请你找出中间被加密的字符串S。
输入:
10
MMATSATMMT
输出 :
SATM
大致思路
这题没啥好说的…题目花里胡哨的, 也就是得到前面 一个 M…T的最小left , 和后面的一个 M…T的最大right
然后把之间的字符串截取出来就是答案
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class Main {
private ReadIn readIn = new ReadIn(System.in);
private PrintWriter printWriter = new PrintWriter(System.out, true);
public void run() throws IOException {
int len = readIn.nextInt();
String str = readIn.next();
int left = 0;
int right = 0;
boolean flag1 = false;
for (int i = 0; i < len; i++) {
char temp = str.charAt(i);
if (!flag1 && temp == 'M') flag1 = true;
if (flag1 && temp == 'T') {
left = i;
break;
}
}
flag1 = false;
for (int i = len - 1; i > 0; i--) {
char temp = str.charAt(i);
if (!flag1 && temp == 'T') flag1 = true;
if (flag1 && temp == 'M') {
right = i;
break;
}
}
printWriter.println(str.substring(left + 1, right));
}
public static void main(String[] args) throws IOException {
new Main().run();
}
static class ReadIn {
private BufferedReader inputStream;
private StringTokenizer tokenizer;
public ReadIn(InputStream input) {
this.inputStream = new BufferedReader(new InputStreamReader(input));
this.tokenizer = new StringTokenizer("");
}
public String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(inputStream.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}
第二题
题目概要
美团打算选调n名业务骨干到n个不同的业务区域,本着能者优先的原则,
公司将这n个人按照业务能力从高到底编号为1~n。
编号靠前的人具有优先选择的权力,每一个人都会填写一个意向,这个意向是一个1~n的排列,
表示一个人希望的去的业务区域顺序,如果有两个人同时希望去某一个业务区域则优先满足编号小的人,
每个人最终只能去一个业务区域。
例如3个人的意向顺序都是1 2 3,则第一个人去1号区域,第二个人由于1号区域被选择了,所以只能选择2号区域,同理第三个人只能选择3号区域。
最终请你输出每个人最终去的区域。
输入:
5
1 5 3 4 2
2 3 5 4 1
5 4 1 2 3
1 2 5 4 3
1 4 5 2 3
输出
1 2 5 4 3
大致思路
由于给的数据, 就是从上到下 , 优先级高的先进行分配
那就没啥好说的… 读取一个人的志愿 … 依次看看是不是前面的人已经抢掉了, 没有抢掉 就填入自己的名字…
唯一需要注意的是输出… 居然是每个人的区域…
我当时一直错误…18% … 看了好久… 我一开始输出的是 每个区域 是什么人… (第一个样本 居然是一模一样的…我醉了)
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class Main {
private ReadIn readIn = new ReadIn(System.in);
private PrintWriter printWriter = new PrintWriter(System.out, true);
public void run() throws IOException {
int k = readIn.nextInt();
int[] map = new int[k + 1]; // 这个可以变成boolean 数组...
int[] res = new int[k]; // 这里是后来加的..
int[] temp = new int[k];
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
temp[j] = readIn.nextInt();
}
for (int m : temp) {
if (map[m] == 0) {
map[m] = i + 1;
res[i] = m;
break;
}
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < k; i++) {
stringBuilder.append(res[i]).append(' '); // 之前输出的是 map 数据..让我看了好久.. 怀疑人生
}
printWriter.println(stringBuilder.toString().trim());
}
public static void main(String[] args) throws IOException {
new Main().run();
}
static class ReadIn {
private BufferedReader inputStream;
private StringTokenizer tokenizer;
public ReadIn(InputStream input) {
this.inputStream = new BufferedReader(new InputStreamReader(input));
this.tokenizer = new StringTokenizer("");
}
public String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(inputStream.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}
第三题
题目概要
小团惹小美生气了,小美要去找小团“讲道理”。小团望风而逃,
他们住的地方可以抽象成一棵有n个结点的树,小美位于x位置,小团位于y位置。
小团和小美每个单位时间内都可以选择不动或者向相邻的位置转移,假设小美足够聪明,很显然最终小团会无路可逃,
只能延缓一下被“讲道理”的时间,请问最多经过多少个单位时间后,小团会被追上。
简单的说, 就是在一个 树上… 2个点在做移动… 你追我赶. 追上的最多时间
输入 :
5 1 2
2 1
3 1
4 2
5 3
解释 : 第一行 分别表示节点个数 , 小美的位置, 小团的位置
后面 是节点个数 - 1 的边(无向边)
**输出: **
2
解释 : 小团先逃到 4 , 小美追到 2
小团无路可走, 小美追到 4 (结束) 2次
大致思路
这题还是挺有意思的, 我的思路是 :
从小团的位置出发, 走过所有的节点, 需要的最少步数 stepB
从小美的位置触发, 走过所有的节点, 需要的最少步数 stepA
只要小美需要的步数 大于 小团… 就说明 小团是逃跑路线… 可以得到最大的值
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class Main {
private ReadIn readIn = new ReadIn(System.in);
private PrintWriter printWriter = new PrintWriter(System.out, true);
public void run() throws IOException {
int k = readIn.nextInt();
int A = readIn.nextInt();
int B = readIn.nextInt();
int[] stepA = new int[k + 1];
int[] stepB = new int[k + 1];
List[] lists = new ArrayList[k + 1];
for (int i = 1; i <= k; i++) {
lists[i] = new ArrayList<Integer>();
}
for (int i = 0; i < k - 1; i++) {
int start = readIn.nextInt();
int end = readIn.nextInt();
lists[start].add(end);
lists[end].add(start);
}
bfs(A, stepA, lists);
bfs(B, stepB, lists);
int max = 0;
for (int i = 1; i <= k; i++) {
if (stepA[i] > stepB[i]) max = Math.max(stepA[i], max);
}
printWriter.println(max);
}
static class Node {
int start;
int step;
public Node(int start, int step) {
this.start = start;
this.step = step;
}
}
private void bfs(int start, int[] steps, List[] map) {
Queue<Node> queue = new LinkedList<>();
queue.add(new Node(start, 0));
while (!queue.isEmpty()) {
final Node parent = queue.poll();
final List<Integer> list = map[parent.start];
for (int end : list) {
if (end != start && steps[end] == 0) {
steps[end] = parent.step + 1;
queue.add(new Node(end, steps[end]));
}
}
}
}
public static void main(String[] args) throws IOException {
new Main().run();
}
static class ReadIn {
private BufferedReader inputStream;
private StringTokenizer tokenizer;
public ReadIn(InputStream input) {
this.inputStream = new BufferedReader(new InputStreamReader(input));
this.tokenizer = new StringTokenizer("");
}
public String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(inputStream.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}
第四题
题目概要
小团从某不知名论坛上突然得到了一个测试默契度的游戏,想和小美玩一次来检验两人的默契程度。
游戏规则十分简单,首先有给出一个长度为n的序列,最大值不超过m。
小团和小美各自选择一个[1,m]之间的整数,设小美选择的是l,小团选择的是r,
我们认为两个人是默契的需要满足以下条件:
- l 小于等于r。
- 对于序列中的元素x,如果0<x<l,或r<x<m+1,则x按其顺序保留下来,要求保留下来的子序列单调不下降。
小团为了表现出与小美最大的默契,因此事先做了功课,他想知道能够使得两人默契的二元组<l,r>一共有多少种。
我们称一个序列A为单调不下降的,当且仅当对于任意的i>j,满足A_i>=A_j。
输入第一行包含两个正整数m和n,表示序列元素的最大值和序列的长度。(1<=n,m<=100000)
输入第二行包含n个正整数,表示该序列。
输入 :
5 5
4 1 4 1 2
输出 : 10
思路
没啥思路- -… 使用的是暴力. … 样本过水了应该…居然能够通过 lucky
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class Main {
private ReadIn readIn = new ReadIn(System.in);
private PrintWriter printWriter = new PrintWriter(System.out, true);
public void run() throws IOException {
int count = readIn.nextInt();
int k = readIn.nextInt();
int[] map = new int[k];
for (int i = 0; i < k; i++) map[i] = readIn.nextInt();
int res = 0;
// int rightMin = 0;
for (int i = 1; i <= count; i++) {
int temp = res;
// rightMin = Math.max(i, rightMin);
for (int j = i; j <= count; j++) {
if (isOk(i, j, map)) {
res += count - j + 1;
// rightMin = j;
break;
}
}
if (temp == res) break;
}
printWriter.println(res);
}
private boolean isOk(int i, int j, int[] map) {
int cur = -1;
for (int num : map) {
if (num < i || num > j) {
if (num < cur) return false;
cur = num;
}
}
return true;
}
public static void main(String[] args) throws IOException {
new Main().run();
}
static class ReadIn {
private BufferedReader inputStream;
private StringTokenizer tokenizer;
public ReadIn(InputStream input) {
this.inputStream = new BufferedReader(new InputStreamReader(input));
this.tokenizer = new StringTokenizer("");
}
public String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(inputStream.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}
第五题
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
public class Main {
private ReadIn readIn = new ReadIn(System.in);
private PrintWriter printWriter = new PrintWriter(System.out, true);
/**
* 小团是一个莫得感情的CtrlCV大师,他有一个下标从1开始的序列A和一个初始全部为-1的序列B,
* 两个序列的长度都是n。他会进行若干次操作,每一次操作,他都会选择A序列中一段连续区间,
* 将其粘贴到B序列中的某一个连续的位置,在这个过程中他也会查询B序列中某一个位置上的值。
* <p>
* 我们用如下的方式表示他的粘贴操作和查询操作:
* <p>
* 粘贴操作:1 k x y,表示把A序列中从下标x位置开始的连续k个元素粘贴到B序列中从下标y开始的连续k个位置上,
* 原始序列中对应的元素被覆盖。(数据保证不会出现粘贴后k个元素超出B序列原有长度的情况)
* <p>
* 查询操作:2 x,表示询问当前B序列下标x处的值是多少。
* <p>
* 5
* 1 2 3 4 5
* 5
* 2 1
* 2 5
* 1 2 3 4
* 2 3
* 2 5
* <p>
* -1
* -1
* -1
* 4
*/
public void run() throws IOException {
int len = readIn.nextInt();
int[] A = new int[len];
int[] B = new int[len];
Arrays.fill(B, -1);
for (int i = 0; i < len; i++) {
A[i] = readIn.nextInt();
}
int k = readIn.nextInt();
while (k-- > 0) {
int ore = readIn.nextInt();
if (ore == 1) {
int tempLen = readIn.nextInt();
int startA = readIn.nextInt() - 1;
int startB = readIn.nextInt() - 1;
System.arraycopy(A, startA, B, startB, tempLen);
} else printWriter.println(B[readIn.nextInt() - 1]);
}
}
public static void main(String[] args) throws IOException {
new Main().run();
}
static class ReadIn {
private BufferedReader inputStream;
private StringTokenizer tokenizer;
public ReadIn(InputStream input) {
this.inputStream = new BufferedReader(new InputStreamReader(input));
this.tokenizer = new StringTokenizer("");
}
public String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(inputStream.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
}
}