栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

2022年4月23日美团笔试

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2022年4月23日美团笔试

目录
  • 1. 考试座位
  • 2. 小美炒股
  • 3. 颜色排序
  • 4. 方格染色
  • 其他

1. 考试座位

题目描述:

现在有n个人坐成一排进行上机考试。但他们有的使用C语言,用C表示;而有的使用Java,用J表示。为了防止他们“友好交流”,小美老师要求任意座位相邻的两人之间使用的语言是不同的。小美每次可以交换相邻两人的位置,现在她想知道最少交换多少次可以满足要求?

输入描述:

输入一个整数n(1≤n≤106) ,表示有n个人。
然后输入n个字母c1,c2,… ,cn(ci∈{C,J})构成的字符串,表示每个人使用的语言。

输出描述:

输出一个整数S,表示最少需要交换S次。若不可能满足要求,则输出-1。

样例输入:

4
CCJJ

样例输出:

1

思路:

  1. 双指针从左往右遍历,只要出现前后一样的情况,就让后面跟他不一样的字符经过多次交换过来
  2. 不懂?给你举个例子CJCJJJJJJJJJJJC………
                                             ↑_________↓
  3. 我要通过11次交换把后面这个C交换到前面来满足前面5个人是正确的,然后往后如此就行

代码实现:

public class Main{
    public static void main(String[] args) {
        //----------------输入------------------//
        Scanner scanner = new Scanner(System.in);
        int n = Integer.parseInt(scanner.nextLine());
        String str = scanner.nextLine();

        char[] s = str.toCharArray();
        int CountC = 0;
        for(int i = 0; i < n; i++){
            if(s[i] == 'C'){
                CountC++;
            }
        }
        int CountJ = n - CountC;
        int res = 0;
        if(Math.abs(CountC-CountJ) > 1){
            System.out.println(-1);//J和C数量之差大于1则肯定排不了座位
        }else{
            res = 0;
            int left = 1, right = 1;//初始化左右指针
            while(left < n-1){
                if(s[left] == s[left-1]){
                    right = right + 1;//right指向left后一个
                    while(right < n-1 && s[left] == s[right]){//right移动到第一个与s[right]不同的元素
                        right++;
                    }
                    if(right == n-1 && s[left] == s[right]){//如果不存在不同的元素跳出
                        break;
                    }
                    char temp = s[left];
                    s[left] = s[right];
                    s[right] = temp;//交换left,right元素
                    res += right - left;//交换次数
                    left++;//左指针后移
                }
                left++;
            }
            if(1 < n && s[n-2] == s[n-1]){//最后两个字符相同的话,应该把其中一个换到开头,这个操作需要交换n次
                res += n;
            }
        }
        System.out.println(res);
    }
}
2. 小美炒股

题目描述:

小美最近在炒股。

小美只关注一支股票,而且她有着预测未来的能力,她提前知道了未来n天的股票价格(第 i 天为ai)。

小美每天只在收盘时的瞬间操作,所以可以认为每天股票价格是不变的。在股市出现剧烈波动时,小美可能赚得过多,为了防止泄露超能力,她决定在总资金超过1e6=1000000之后不再买入(但是卖出时间不定,仍要求卖出时有最大收益)。超过100万后,如果她还想买入,可以捐款一些资金,使自己的资金不超过100万,这样她可以在超过100万前继续买入。(即资金超过100万后,找以100万为本金的单次买卖的最大收益)

现在小美现在有1000元,她想知道如果一直最优抉择,她在n天后拥有多少钱?请你帮帮她。(允许不买任意股票,购入股票数必须为整数)

输入描述:

对于每一组数据,第一行一个正整数n;
第二行n个空格隔开的整数 a1,a2, … ,an
1≤n≤10000 ,1≤ai≤1000

输出描述:

输出一个整数,表示小美最优决策后的金钱。

样例输入:

5
101 102 100 101 103

样例输出:

1039

思路:
原本想着用动态规划dp数组,但是这个玩意儿涉及本金,还涉及手头不能超过100万。着实受不了,所以我直接用回溯法了,如果大家有好的想法,欢迎告诉我呀。秋梨膏=.=

标准版:

public class Main {
    static int up = 1000000;

    public static void main(String[] args) {
        //----------------输入------------------//
        Scanner scanner = new Scanner(System.in);
        int n = Integer.parseInt(scanner.nextLine());
        String str = scanner.nextLine();

        //----------------整理输入------------------//
        //因为我只会在波峰波谷的地方操作,所以我只记录波峰波谷就行,这么好用的预见未来能里肯定要好好用啊
        List list = new ArrayList<>();
        int first = Integer.parseInt(str.split(" ")[0]);
        int mid = Integer.parseInt(str.split(" ")[1]);
        if (first < mid) {
            list.add(first);
        }
        int flag = mid - first;
        for (int i = 1; i < n; i++) {
            int pre = Integer.parseInt(str.split(" ")[i - 1]);
            int next = Integer.parseInt(str.split(" ")[i]);
            if (flag * (next - pre) < 0) {
                list.add(pre);
                flag = 0 - flag;
            }
        }
        int last = Integer.parseInt(str.split(" ")[n - 1]);
        if (Integer.parseInt(str.split(" ")[n - 2]) < last) {
            list.add(last);
        }

        //TODO
        int[] prices = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            prices[i] = list.get(i);
        }

        System.out.println(Math.max(dynamic(prices, 1, 1000 / prices[0], 1000 % prices[0]), 1000));
    }

    public static int dynamic(int[] prices, int start, int n, int money) {//prices为操作,start为从什么时候开始操作,n为当前持有的股票数
        int max = 0;
        if (start == prices.length - 1) {
            if (n > 0) {
                return money + n * prices[start];
            } else {
                return money;
            }
        }

        if (n > 0) {
            //此时可以卖也可以不卖
            max = Math.max(dynamic(prices, start + 1, n, money), dynamic(prices, start + 1, 0, money + prices[start] * n));
        } else {
            //此时可以买也可以不买
            if (money > up) {
                max = Math.max(dynamic(prices, start + 1, 0, money), dynamic(prices, start + 1, up / prices[start], up % prices[start]));
            } else {
                max = Math.max(dynamic(prices, start + 1, 0, money), dynamic(prices, start + 1, money / prices[start], money % prices[start]));
            }
        }
        return max;
    }
}

代码是不是看上去好乱,加上回溯,我都不知道到底哪里买入哪里卖出的。没事,我这还有更强的杀招,什么时候买入什么时候卖出。我来告诉你:

详细版:

public class Main {
    static int up = 1000000;
    static List outprint = new ArrayList<>();

    public static void main(String[] args) {
        //----------------输入------------------//
        Scanner scanner = new Scanner(System.in);
        int n = Integer.parseInt(scanner.nextLine());
        String str = scanner.nextLine();

        //----------------整理输入------------------//
        List list = new ArrayList<>();
        int first = Integer.parseInt(str.split(" ")[0]);
        int mid = Integer.parseInt(str.split(" ")[1]);
        if (first < mid) {
            list.add(first);
        }
        int flag = mid - first;
        for (int i = 1; i < n; i++) {
            int pre = Integer.parseInt(str.split(" ")[i - 1]);
            int next = Integer.parseInt(str.split(" ")[i]);
            if (flag * (next - pre) < 0) {
                list.add(pre);
                flag = 0 - flag;
            }
        }
        int last = Integer.parseInt(str.split(" ")[n - 1]);
        if (Integer.parseInt(str.split(" ")[n - 2]) < last) {
            list.add(last);
        }

        //TODO
        int[] prices = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            prices[i] = list.get(i);
        }
        int dy = dynamic(prices, 1, 1000 / prices[0], 1000 % prices[0]);
        if (dy > 1000) {
            outprint.add("在价格为" + prices[0] + "时买入");
        }
        Collections.reverse(outprint);
        outprint.remove(outprint.size() - 1);
        outprint.add("最终手里有" + dy);
        System.out.println(outprint);
    }

    public static int dynamic(int[] prices, int start, int n, int money) {//prices为操作,start为从什么时候开始操作,n为当前持有的股票数
        int max = 0;
        if (start == prices.length - 1) {
            if (n > 0) {
                int res = money + n * prices[start];
                outprint.add("在价格为" + prices[start] + "时卖出");
                return res;
            } else {
                return money;
            }
        }

        if (n > 0) {
            //此时可以卖也可以不卖
            int no = dynamic(prices, start + 1, n, money);
            int yes = dynamic(prices, start + 1, 0, money + prices[start] * n);
            if (no < yes) {
                outprint.add("在价格为" + prices[start] + "时卖出");
                max = yes;
            } else {
                max = no;
            }
        } else {
            //此时可以买也可以不买
            if (money > up) {
                int no = dynamic(prices, start + 1, 0, money);
                int yes = dynamic(prices, start + 1, up / prices[start], up % prices[start]);
                if (yes > no) {
                    outprint.add("在价格为" + prices[start] + "时买入" + "此时因为手头超过100万了,所以我捐了" + (money - up));
                    max = yes;
                } else {
                    max = no;
                }
            } else {
                int no = dynamic(prices, start + 1, 0, money);
                int yes = dynamic(prices, start + 1, money / prices[start], money % prices[start]);
                if (yes > no) {
                    outprint.add("在价格为" + prices[start] + "时买入");
                    max = yes;
                } else {
                    max = no;
                }
            }
        }
        return max;
    }
}
3. 颜色排序

题目描述:

小美得到了一个长度为n的整数序列,并且序列上每个数字都被染上了颜色1~n的其中一种。现在小美想要给这个序列按从小到大排序,但她每次操作只能交换相邻两个数,并且这两个数的颜色要不相同。她想知道进行若干次操作之后能不能给这个序列排好序。

输入描述:

第一行一个正整数T,表示有T组数据。

对于每一组数据,第一行一个正整数n,表示这个序列的长度;第二行n个正整数ai,表示该序列;第三行n个正整数ci,表示第 i 个数的颜色。

数字间两两有空格隔开

1≤T≤8,1≤n≤104 ,1≤ai,ci≤n

输出描述:

对于每一组数据,如果可以排好序,输出一行Yes;否则,输出一行No。

样例输入:

2
5
3 2 4 1 5
1 2 2 3 1
3
2 2 1
1 1 1

样例输出:

Yes
No

样例解释:

第一组样例可以如下排序:
[3 2 4 1 5] -> [2 3 4 1 5] -> [2 3 1 4 5] -> [2 1 3 4 5] -> [1 2 3 4 5]

思路:同色不能交换的意思也就是说同色的相对顺序不能改变,如此一来我枚举每一种颜色, 如果相同颜色的数字都是有序的,那么就返回Yes,否则返回No。

public class Main {
    public static void main(String[] args) {
        //------------------输入--------------------//
        Scanner scanner = new Scanner(System.in);
        int T = Integer.parseInt(scanner.nextLine());
        for (int i = 0; i < T; i++) {
            int n = Integer.parseInt(scanner.nextLine());
            int[] nums = new int[n];
            String str1 = scanner.nextLine();
            for (int j = 0; j < n; j++) {
                nums[j] = Integer.parseInt(str1.split(" ")[j]);
            }
            int[] colors = new int[n];
            String st2 = scanner.nextLine();
            for (int j = 0; j < n; j++) {
                colors[j] = Integer.parseInt(st2.split(" ")[j]);
            }
            //TODO
            System.out.println(colorrank(nums, colors, n));
        }
    }

    public static String colorrank(int[] nums, int[] colors, int n) {
        //对于某个颜色,必须是有序的
        Map map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            if (map.containsKey(colors[i])) {
                if (map.get(colors[i]) > nums[i]) {
                    return "No";
                } else {
                    map.put(colors[i], nums[i]);
                }
            } else {
                map.put(colors[i], nums[i]);
            }
        }
        return "Yes";
    }
}
4. 方格染色

题目描述:

小美从老师那里得到了一张N x M的方格纸(即N行M列),上面每个方格都染上了一种颜色。

老师又给了小美另一张大小一模一样但是没有染色的方格纸,并对于方格纸上的每种颜色,老师给了她一些大小为2 x 2的颜料笔,每次可以选择一个大小恰好为2 x 2的方格染成同一种颜色(对已染色的方格也可以染色,同一种颜料笔可以用多次)。

老师想考考小美:能不能用这些颜料笔对这张未染色的方格纸进行染色,使得其与已染色的这张方格纸一模一样?

输入描述:

第一行一个正整数T,表示有T组数据。

对于每一组数据,第一行输入两个正整数N,M;

接下来N行,每行M个数,第 i 行第 j 列的数表示为 Cij,表示这个位置的方格的颜色。

数字间两两有空格隔开。

2≤N,M≤200 , 1≤Cij≤NM , 1≤T≤10

输出描述:

对于每一组数据,如果可以染成与已染色的方格纸相同的话,输出一行Yes;否则,输出一行No。

样例输入:

2
4 4
5 5 3 3
1 1 5 3
2 2 5 4
2 2 4 4
3 4
1 1 1 1
2 2 3 1
2 2 1 1

样例输出:

Yes
No

思路:
染色的题目一般倒着做, 我最后一次涂抹的地方肯定是一块完整的2*2的同色快。那么我倒着来,我把它擦了(都换成-1)。然后我重新遍历,只要是一个2*2里出现同色块或者没有颜色(-1),那说明我之前在这里涂抹过,我把他们都擦掉。循环往复。最后如果我看整张纸是白纸了,那说明确实我可以画出来。只要还有颜色,直接返回No

代码实现:

public class Main {
    public static void main(String[] args) {
        //-------------输入-------------------//
        Scanner scanner = new Scanner(System.in);
        int T = Integer.parseInt(scanner.nextLine());
        for (int i = 0; i < T; i++) {
            String str1 = scanner.nextLine();
            int n = Integer.parseInt(str1.split(" ")[0]);
            int m = Integer.parseInt(str1.split(" ")[1]);
            int[][] colors = new int[n][m];
            for (int j = 0; j < n; j++) {
                String str2 = scanner.nextLine();
                for (int k = 0; k < m; k++) {
                    colors[j][k] = Integer.parseInt(str2.split(" ")[k]);
                }
            }
            System.out.println(give_it_color_see(colors, n, m));
        }
    }

    public static String give_it_color_see(int[][] colors, int n, int m) {
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < m - 1; j++) {
                //将[i,j]作为左上角
                int color = 0;
                if (colors[i][j] != -1) {
                    color = colors[i][j];
                } else if (colors[i + 1][j] != -1) {
                    color = colors[i + 1][j];
                } else if (colors[i][j + 1] != -1) {
                    color = colors[i][j + 1];
                } else if (colors[i + 1][j + 1] != -1) {
                    color = colors[i + 1][j + 1];
                }
                if (color == 0) {
                    continue;
                }
                if ((colors[i][j] == color || colors[i][j] == -1) && (colors[i][j + 1] == color || colors[i][j + 1] == -1) && (colors[i + 1][j] == color || colors[i + 1][j] == -1) && (colors[i + 1][j + 1] == color || colors[i + 1][j + 1] == -1)) {
                    colors[i][j] = -1;
                    colors[i][j + 1] = -1;
                    colors[i + 1][j] = -1;
                    colors[i + 1][j + 1] = -1;
                    i = 0;
                    j = -1;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (colors[i][j] != -1) {
                    return "No";
                }
            }
        }
        return "Yes";
    }
}
其他

Java的二维数组打印方式:
用Arrays.deepToString()

public class Main {
    public static void main(String[] args) {
        int[][] array = {{1, 2, 3}, {4, 5, 6}};
        System.out.println(Arrays.toString(array));//打印的是地址
        System.out.println(Arrays.deepToString(array));
    }
}

本人愚笨,上述的代码也不知道是否正确,如果有发现错误或者有更好的方法,请评论,谢谢各位大哥大嫂了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/844747.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号