2021年华为OD社招牛客网机试总结(20210621)

最长递增子序列

https://www.nowcoder.com/practice/9cf027bf54714ad889d4f30ff0ae5481

2021年华为OD笔试总结(20200621)

难度一星题1:最小合并数

输入一组整数,要求输出由输入整数中最多3个整数按任意顺序合并(拼接)成最小整数。数组大小n<100,每个输入数据的范围0<x<10000,输入数组包含的整数可能小于3个。输入输出示例:

输入:

51,2,34,58,116

输出:

23451

这题主要考察数理逻辑,如果把输入整数转换为字符串拼接然后转换为整数稍微麻烦一点。这里直接根据题目条件中数据范围0<x<10000,将输入整数中最小的3个全部对其到10000位,直接整数比较就行,但是这样引入了一个边角情况的处理需要留意

Java解法:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        int cur = 0, cnt = 0;
        HashMap<Integer, Integer> map = new HashMap<>();
        PriorityQueue<Integer> minQueue = new PriorityQueue<>();
        PriorityQueue<Integer> res = new PriorityQueue<>(3);
        Scanner sc = new Scanner(System.in);
        String getLine = sc.nextLine();
        String[] fields = getLine.split(",\\s*");
        for (String num: fields) {
            ++cnt;
            cur = Integer.parseInt(num);
            minQueue.offer(cur);    // java优先队列默认从小到大排序
        }

        if (cnt > 3) {
            cnt = 3;
        }
        int shift, alignedVal;
        while (cnt > 0) {
            cur = minQueue.poll();
            alignedVal = cur;
            shift = 0;
            while (alignedVal < 10000) {    //把输入的每个整数都对齐到5位数
                alignedVal *= 10;
                ++shift;
            }
            // 可能存在58和580这样的数据对齐后是同一个数,这种情况要求58对齐后更小,
            // 所以都减去乘以10的次数
            alignedVal -= shift;
            map.put(alignedVal, cur);    // 这儿数据量不大,直接使用哈希保存对应关系比较省事
            res.offer(alignedVal);
            --cnt;
        }

        Integer val;
        while((val = res.poll()) != null) {
            System.out.printf("%d", map.get(val));
        }
        System.out.println();
    }
}

难度一星题2:统计数据宽度取模后最多的有效数

定义一种数据宽度某一模数a的取模运算,并且取模结果小于数值c时,把该数计做有效数,否则计做无效数。例如a=4, c=3时,对269628502的宽度取模,269628502 % 4 = 0x10123456 % 4 = (0x10+0x12+0x34+0x56) % 4 = 0,取模结果0<4,所以269628502计为有效数。那么,现在要求对输入的一组数据的宽度取模后,需要统计出相同结果最多的有效数个数并输出。输入数据中,读取第一个数作为模数a,第二个数作为有效数判断条件c。输入输出示例:

输入:

3,4,9,1899,2004399,20128,1,0,987642,1588,626

统计取模结果后的每个有效数为[1,2, 3, 2, 1, 1, 3, 2, 2],结果相同的有效数最多的是2,个数为4,所以输出:

4

这个题目在原文中的描述有点复杂,但是要求的工作却很简单。当时没有通过一个case,不确定是否有审题正确,只想提醒大家碰到这种啰嗦的问题描述还是静下心要好好审题

难度二星题1:书本的最大堆叠高度

这里有一堆不同高度和宽度的图书,需要你按从大到小的循序把它们水平堆叠到一起,意即堆叠时要求上层的图书的高度和宽度都不超过下层的图书,而且不能将书本旋转,输入中每一对数分别对应书本的高度和宽度,要求输出书本最大堆叠高度。输入输出示例:

输入:

27,18 32,24 20,28 31,20 26,19

输出:

3

这个题目其实是NC91.最长递增子序列稍微包装了一下,当时就往动态规划的方向怎么也想不通,考完一下就想起来了(⊙﹏⊙)。所以考试还是要保持冷静,同时我太菜了

Java解法:

package com.company;

import java.util.*;

public class Main {
    public static void main(String[] args) {
        int height, width;
        edge book;
        PriorityQueue<edge> bookx = new PriorityQueue<edge>(new Comparator<edge>() {
            public int compare(edge a, edge b) {
                if (a.x == b.x) {       // compare中两数相等时要求返回0
                    if (a.y == b.y) {
                        return 0;
                    } else {
                        return b.y - a.y;   // 图书的高相等时,需要把较宽的书放在下面
                    }
                } else {
                    return b.x - a.x;
                }
            }
        });
        Scanner sc = new Scanner(System.in);
        String inputLine = sc.nextLine();
        String[] fields = inputLine.split(" ");
        for (String length: fields) {
            height = Integer.parseInt(length.split(",")[0]);
            width = Integer.parseInt(length.split(",")[1]);
            book = new edge(height, width);
            bookx.offer(book);
        }

        int decreaseMax = 0, bookNum = bookx.size();
        int[] decreaseWidth = new int[bookNum];
        int[] widthIndex = new int[bookNum];
        edge res;
        res = bookx.poll();
        decreaseWidth[0] = res.y;
        widthIndex[decreaseMax] = 0;
        ++decreaseMax;
        while((res = bookx.poll()) != null) {   // 使用poll方法才可以从优先队列中取到有序的数据
            if (res.y <= decreaseWidth[decreaseMax-1]) {    // 高度和宽度相同的图书可以堆叠
                decreaseWidth[decreaseMax] = res.y;
                widthIndex[decreaseMax] = decreaseMax;
                ++decreaseMax;
            } else {
                for (int i=0; i<decreaseMax; ++i) {
                    if (res.y >= decreaseWidth[i]) {    // 注意等号
                        decreaseWidth[i] = res.y;
                        widthIndex[decreaseMax] = i;
                        break;
                    }
                }
            }
        }
        System.out.printf("%d\n", decreaseMax);
    }

    private static class edge {
        int x;
        int y;

        public edge(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}

总结

整体看来华为的OD考试难度比往年有所加大(没错,我已经不是第一次考了),我这3题在题库中都不能找到原题。而且改编的题目描述可能没那么容易一眼看出解决方案,所以再次强调冷静认真审题非常重要。这里老生常谈的解题技巧我就不罗嗦了,主要说一下个人的考试感悟。
首先这次对于我巨坑的一点是,所有的输入数据都要从控制台接收,而我刚从C语言切到Java刷题,对于Java格式化输入的方法不太熟悉。幸亏有例题的解答给出了接收输入的方式,但是,更坑的是示例的while(sc.hasNext())nextInt用法是错误的,因为1.hasNext等方法读取到回车后仍期望读取到EOF造成阻塞;2.nextInt等方法不会扫描整数后的空格,而next方***扫描子串前后的空格,所以获取字符流中的整数时要使用skip方法来跳过中间的一些空格(或者其他分隔符)。
第二点,牛客的机试编辑器真的不太好用,不知道为什么我切出浏览器再切回的时候,编辑模式就变成了覆盖输入,不过还好机试允许在自己的IDE中调试代码问题不大。
最后也是最重要的一点,既然现在允许我们在IDE中调试代码,我们在解答时候特别容易忘记一些边角情况的处理。考试前一定要会熟练使用IDE调试代码,要相信计算机永远是对的。在运行异常和一些case通不过的时候,不要觉得自己单单紧盯着代码就能分析出毛病在哪里,而是该考虑在哪儿多加一个断点,或者有没有其他不能按预期很好处理的输入数据情况没有照顾到。

全部评论
第一题什么鬼的示例23451<116234
2 回复 分享
发布于 2021-07-19 23:06
第一题没看懂题意 ,题目“一字千金”
1 回复 分享
发布于 2021-06-26 21:18
第三题不能用最长递增子序列吧?用自定义排序加判断
点赞 回复 分享
发布于 2022-02-25 10:57
机试时长是多久?
点赞 回复 分享
发布于 2022-01-25 10:56
import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String s = scanner.nextLine(); String[] ss = s.split(","); Arrays.sort(ss, Comparator.comparingInt(Integer::parseInt)); String[] ss2; if (ss.length < 3){ ss2 = new String[ss.length]; } else { ss2 = new String[3]; } System.arraycopy(ss, 0, ss2, 0, ss2.length); Arrays.sort(ss2); StringBuilder builder = new StringBuilder(); for (String value : ss2) { builder.append(value); } System.out.println(builder.toString()); } }
点赞 回复 分享
发布于 2021-12-31 19:17
第二题没看懂
点赞 回复 分享
发布于 2021-10-05 11:08

相关推荐

2025-12-24 15:25
已编辑
门头沟学院 前端工程师
是腾讯的csig腾讯云,前天晚上九点突然打电话约面,激动的通宵学了一晚上,第二天状态很差改了今天(以后再也不通宵学习了)感觉自己浪费了面试官一个半小时单纯手写+场景,无八股无项目无算法,打击真的很大,全是在面试官提醒的情况下完成的,自己技术方面真的还是有待提高,实力匹配不上大厂和已经面试的两个公司完全不一样,很注重编码能力和解决问题的能力,然而我这两个方面都很薄弱,面试官人很好很耐心的等我写完题目,遇到瓶颈也会提醒我,写不出题也会很耐心的跟我讲解好感动,到最后面试结束还安慰我打算把下周最后一场面试面完之后就不面啦,如果能去实习还是很开心,但是最重要的还是好好努力提高技术以下是面经第一题//&nbsp;实现一个解析&nbsp;url&nbsp;参数的函数function&nbsp;parseUrl(urlStr)&nbsp;{//&nbsp;TODO}parseUrl('*********************************************');//&nbsp;返回&nbsp;{a:&nbsp;1,&nbsp;b:&nbsp;2,&nbsp;c:&nbsp;3}追问:在链接里见过什么部分?用&nbsp;hash&nbsp;路由的话放在哪第二题//&nbsp;考虑有一个异步任务要执行,返回&nbsp;Promise,这个任务可能会失败,请实现&nbsp;retry&nbsp;方法,返回新方法,可以在失败后自动重试指定的次数。/***&nbsp;异步任务重试*&nbsp;@param&nbsp;task&nbsp;要执行的异步任务*&nbsp;@param&nbsp;times&nbsp;需要重试的次数,默认为&nbsp;3&nbsp;次*/function&nbsp;retry(task,&nbsp;times&nbsp;=&nbsp;3)&nbsp;{//&nbsp;TODO:&nbsp;请实现}//&nbsp;---------------测试示例&nbsp;----------------//&nbsp;原方法const&nbsp;request&nbsp;=&nbsp;async&nbsp;(data)&nbsp;=&gt;&nbsp;{//&nbsp;模拟失败if&nbsp;(Math.random()&nbsp;&lt;&nbsp;0.7)&nbsp;{throw&nbsp;new&nbsp;Error('request&nbsp;failed');}const&nbsp;res&nbsp;=&nbsp;await&nbsp;fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;,&nbsp;{method:&nbsp;'POST',body:&nbsp;JSON.stringify(data),});return&nbsp;res.json();}//&nbsp;新的方法const&nbsp;requestWithRetry&nbsp;=&nbsp;retry(request);//&nbsp;使用async&nbsp;function&nbsp;run()&nbsp;{const&nbsp;res&nbsp;=&nbsp;await&nbsp;requestWithRetry({&nbsp;body:&nbsp;'content'&nbsp;});console.log(res);}run();第三题就是给&nbsp;retry&nbsp;函数添加类型注释,用到泛型第四题:在组件库中将&nbsp;Alert&nbsp;用&nbsp;api&nbsp;的形式实现(应该就是&nbsp;message&nbsp;这个组件)怎么渲染到一个浮层里而不是原地渲染出来
不知道怎么取名字_:技术这个东西,太杂了,而且要下功夫的
查看5道真题和解析
点赞 评论 收藏
分享
评论
10
33
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务