2020-08-29 ---- 美团点评 笔试

美团笔试

一共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,

我们认为两个人是默契的需要满足以下条件:

  1. l 小于等于r。

  2. 对于序列中的元素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());
        }
    }

}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值