2021-03-31 华为校园招聘 软件 笔试题

一共3道编程题

第一题:足球赛得分

题目描述:

有一场双循环赛制(每个队都要主动和其他所有队打一次)的足球赛,胜、负、平分别得3、0、1分,现在给你一场球赛的比分表,需要你按照积分高低输出排名,积分相同的就按队伍名字排序。球队最多26个,球队名称范围为a-z

输入输出样例:

Input: (计分板)
a-b 3:0
a-c 2:1
b-a 1:1
c-a 0:1
b-c 4:3
c-b 2:2
Output:
a 10,b 5,c 1

a总共赢3场、平1场,积3*3+1=10分,
b总共赢1场、平2场、负1场,积3+2*1+0=5分,
c总共赢0场、平1场、负3场,积1+0=1分,

解法:

这里处理输入是一个比较头疼的点,需要多次分割。解法没啥好说的,直接模拟就行。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

/**
 * Main class
 *
 * @author Soarkey
 * @date 2021/3/31
 */
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(new BufferedInputStream(System.in));
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

        // 用26长度先保存队伍
        Team[] team = new Team[26];
        while (in.hasNext()) {
            String[] line = in.nextLine().split(" ");
            // 队伍 a-b
            String[] t = line[0].split("-");
            // 得分 x:y
            String[] s = line[1].split(":");
            // String转为int
            int x = Integer.parseInt(s[0]);
            int y = Integer.parseInt(s[1]);
            if (x > y) {
                // a队胜
                x = 3;
                y = 0;
            } else if (x == y) {
                // 平
                x = 1;
                y = 1;
            } else {
                // b队胜
                x = 0;
                y = 3;
            }
            // t[0].charAt(0) - 'a' 代表a队在数组中的下标
            char a = t[0].charAt(0);
            // t[1].charAt(0) - 'a' 代表b队在数组中的下标
            char b = t[1].charAt(0);

            team[a - 'a'] = team[a - 'a'] == null ? new Team(a, 0) : team[a - 'a'];
            team[a - 'a'].score += x;

            team[b - 'a'] = team[b - 'a'] == null ? new Team(b, 0) : team[b - 'a'];
            team[b - 'a'].score += y;
        }

        StringBuilder builder = new StringBuilder();
        // 按照得分和队名进行排序
        Arrays.sort(team, (a, b) -> {
            if (a == null || b == null) {
                return -1;
            }
            if (a.score != b.score) {
                return b.score - a.score;
            } else {
                return a.name - b.name;
            }
        });
        // 输出结果
        for (int i = 0; i < 26; ++i) {
            if (team[i] != null) {
                builder.append(team[i].name + " " + team[i].score + ",");
            }
        }
        builder.deleteCharAt(builder.length() - 1);
        out.println(builder);

        in.close();
        out.close();
    }

    /**
     * 队伍类
     */
    static class Team {
        // 队伍名称
        char name;
        // 累积得分
        int score;

        Team(char name, int score) {
            this.name = name;
            this.score = score;
        }
    }
}

第二题:猜帽子数量

题目描述:

一些员工玩游戏, 每个人都带了一顶有颜色的帽子,有一部分员工会反馈 帽子跟他颜色一样的人 有多少个,组成了一个数组。现在给你这个数组,让你猜出最少有多少个员工在玩这个游戏。

这道题目的题面挺难懂,得结合具体输入输出才能理解。

输入输出样例:

Input:
[1, 1, 2]
[1, 1, 2, 1, 1] // 这个是我自己加的
[0, 0, 0, 0] // 补充!
Output:
5
7
4

第一个输入的意思就是有3个人报了帽子数量,我们可以先假设为三个人的帽子颜色为a、b、c。
第一个人和第二个人都说还有1个人的帽子颜色跟他一样,如果他俩帽子颜色不同,那至少有4个人在玩游戏,而如果他俩帽子颜色一样的话,玩游戏的人最少就为2个,就是他们自己。
第三个人说还有2个人帽子颜色跟他一样,说明玩游戏的人当中有3个人帽子都是一样的颜色,显然不可能是第一个人和第二个人帽子的颜色,不然就矛盾了。
所以结果为2+3=5

牛友可以自己算第二个试一试。

解法:

我用的是hashmap来根据相同颜色帽子数量来进行统计的,只过了50%,估计是漏了一些条件,有知道的同学欢迎评论区解惑。

补充:后续分析可能是因为漏掉了[0,0,0,0]这个测试用例,这个测试用例可能会导致元素没办法正常remove,因此修改了一下代码,可惜没有验证的机会了。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * Main class
 * 只通过了50%
 * @author Soarkey
 * @date 2021/3/31
 */
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(new BufferedInputStream(System.in));
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

        while (in.hasNext()) {
            String line = in.nextLine();
            line = line.substring(1, line.length() - 1).replace(" ", "");
            if (line.length() == 0) {
                out.println("0");
                continue;
            }

            String[] hatsStr = line.split(",");
            int[] hats = new int[hatsStr.length];
            for (int i = 0; i < hatsStr.length; ++i) {
                hats[i] = Integer.parseInt(hatsStr[i]);
            }
            Arrays.sort(hats);
            Map<Integer, Integer> map = new HashMap<>();

            int totalHat = 0;
            for (int hat : hats) {
                int t = hat + 1;
                if (map.containsKey(t)) {
                    if (map.get(t) - 1 == 0) {
                        map.remove(t);
                        totalHat += t;
                    } else {
                        map.put(t, map.get(t) - 1);
                    }
                } else {
                    // **************** 修改 ******************* //  
                    if(t == 1){
                        // cover有人报的帽子数量为0的情况
                        totalHat += 1;
                    } else {
                        map.put(t, t - 1);
                    }
                    // **************************************** //
                }
            }
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                totalHat += entry.getKey();
            }
            out.println(totalHat);
        }

        in.close();
        out.close();
    }
}

第三题:游标匹配问题

题目描述:

给定一个字符串s和一个游标,游标指向起点start,另外给定一个字符串pattern,要求移动游标(可以向左向右循环移动,即如果移动到了边界可以跳到另一侧)来匹配字符串pattern,问匹配完成最少需要游标移动多少次。

输入输出样例:

Input:
aemoyn // 字符串s
amo // 待匹配的字符串pattern
0 // 游标起点start

// 下面的是我自己加的用例
aasasfsf
asf
2
Output:
3 // 只有一种情况,起点在0处,匹配到a,游标向右移动两次,匹配到m,继续向右移动一次匹配到o,完成

3 // 我自己加的用例输出

解法:

我用的dfs的思路,但是超时了,只过了70%,目测应该用dp来做,但是无奈没想到转移方程,放一下我的丑陋代码供各位同学参考吧~

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;

/**
 * Main class
 * 超时 70%
 *
 * @author Soarkey
 * @date 2021/3/31
 */
public class Main {
    static int ans;

    public static void main(String[] args) {
        Scanner in = new Scanner(new BufferedInputStream(System.in));
        PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

        while (in.hasNext()) {
            String s = in.nextLine();
            String pattern = in.nextLine();
            // 转成字符数组能加快取第i位的速度,以空间换时间
            char[] sc = s.toCharArray();
            char[] pc = pattern.toCharArray();
            int start = in.nextInt();

            ans = Integer.MAX_VALUE;
            dfs(sc, pc, start, 0, 0);

            out.println(ans);
        }

        in.close();
        out.close();
    }

    /**
     * 匹配到第 k 位
     */
    public static void dfs(char[] sc, char[] pc, int start, int k, int step) {
        if (k == pc.length) {
            ans = Math.min(ans, step);
            return;
        }
        if (step >= ans) {
            return;
        }

        for (int j = 0; j < sc.length; j++) {
            if (pc[k] == sc[j]) {
                int t = Math.abs(j - start);
                dfs(sc, pc, j, k + 1,
                        step + Math.min(t, Math.abs(sc.length - t))
                );
            }
        }
    }
}
#笔经##Java工程师#
全部评论
补充:第二题和leetcode题  [781. 森林中的兔子 https://leetcode-cn.com/problems/rabbits-in-forest/submissions/] 是一样的
1 回复 分享
发布于 2021-04-04 13:39
def solution():     string = input("")     pattern = input("")     start = int(input(""))     m,n = len(string),len(pattern)     locations = defaultdict(Letter)     if string[start] == pattern[0]:         pattern = pattern[1:] #一开始就匹配成功这种情况纯粹是捣乱的,会导致后边使用bisect_right错误,也就是需要考虑当前的p的位置也算数,但是除了第一个点,当前位置的p都是上一次的结果,所以不算数     ans = -start
1 回复 分享
发布于 2021-09-09 23:53
楼主,我想问一下,笔试后你是在哪里看到题目和自己的代码啊,我也想复盘,找不到题目入口了
点赞 回复 分享
发布于 2021-04-04 14:26
请问大佬是投的什么部门啊
点赞 回复 分享
发布于 2021-04-06 17:44
第二题我是这么做的(我没参加笔试,纯粹看你的题写的) from collections import Counter nums = list(map(lambda x: int(x)+1,input("").split())) nums = Counter(nums) result = 0 #print(nums) for key,value in nums.items():     result+=value//key*key     if value%key:         result+=key print(result)
点赞 回复 分享
发布于 2021-09-09 21:59
第三题我想了一下怎么更快,后来是需要将数据的位置进行提前的记录,然后每个字母需要保有一个现在的位置,每次找下一个字母的位置的时候,使用二分法找到下一个位置,代码在上边。
点赞 回复 分享
发布于 2021-09-09 22:41
#coding:utf-8 """ aemoyn amo 0 answer:3 aasasfsf sfa 1 answer:7 aasaa ssss 1 answer:16 """ from collections import defaultdict import bisect class Letter(object):     def __init__(self):         self.locations = []         self.p = 0
点赞 回复 分享
发布于 2021-09-09 23:52
我想问一下你这个就是三道编程题就ok了对吧,有没有选择题之类的?
点赞 回复 分享
发布于 2021-09-28 20:11

相关推荐

爱看电影的杨桃allin春招:我感觉你在炫耀
点赞 评论 收藏
分享
10-15 15:00
潍坊学院 golang
跨考小白:这又不是官方
投递拼多多集团-PDD等公司10个岗位
点赞 评论 收藏
分享
评论
10
42
分享
牛客网
牛客企业服务