华为 SWE 实习岗 笔试题 JAVA

最近又参与了一场华为的软件开发实习岗的笔试,于是想将题目分享一下~

如果有啥更好的想法欢迎交流~

Here We Go!

题目一

幼儿园老师安排小朋友做游戏,现在需要给 N 个小朋友进行分组,老师让每个同学写一个名字,代表这位小朋友想和谁分一组。请问老师现在满足所有小朋友意愿的情况下,最多可以将班级分成多少组?

输入描述

第一行输入N,0 < N ≤ 10000
接下来是N行代表每个小朋友希望和谁分到一组,如"John Jack",代表John希望和Jack分到一组,两个名字之间以空格分割,名字本身不存在空格。

输出描述

分组的最多数量

示例输入

6
Jack Tom
Alice John
Jessica Leonie
Tom Alice
John Jack
Leonia Jessica

示例输出

2

示例说明

Jack、Tom、Alice、John分为一组,Jessica和Leonie一组,一共两组。

思路
考察的是并查集的知识。

假设每个小朋友是一个节点(图的节点),那么意愿的双方节点之间连接一条线。那么最后同属一个图中的节点(小朋友)可分为一组。

最后计算一共有多少个图即可。

并查集的思想是 通过标记确定该顶点所在的组

所以对于一个n个小朋友,n条边的图,我们需要新建一个长度为n的数组f,f[n]代表点n的小朋友团队的“代表人”,当两个点所在团伙“代表人”相同,则这两个点所在小朋友则是相同的。

初始化数组f的时候使其f[i] = i,接着假如1号小朋友想和3号小朋友组队,则不妨令f[3] = f[0];那么这里我们默认下标最小的小朋友为团队的“代表人”,同时“代表人”必须有f[x] = x。

示例代码

wait~

题目二

给定 N 个任务(1≤N≤100) ,任务编号从0开始顺序累加,这N个任务在系统中排队顺序执行,每个任务的自身执行时间为非负整数,依次为t1,12…tn。

部分任务之间存在依赖关系的,某任务所依赖的任务如果没有执行,则该任务需要重回队尾重新排队。只有任务执行以及任务排队等待会消耗时间,其余操作消耗时间忽略不计。

请计算每个任务的实际执行时间(实际执行时间=任务自身执行的时间+在队列中等待其他任务执行的时间)

输入描述

第一行输入按照任务编号递增的顺序表示N个任务的自身执行时间,为逗号分隔的字符串,执行时间取值范围[1,999]。例如:1,3,4 (逗号前后没有空格),表示一共3个任务,每个任务的自身执行时间分别为1,3,4。

第二行输入表示任务之间的依赖关系,为逗号分隔的字符串,每个依赖关系都表明了两个任务编号之间的依赖关系,例如:0->2,表示0号任务依赖于2号任务。

输出描述

按照任务编号递增的顺序,输出每个任务的实际执行时间,以逗号分隔,逗号前后不要空格,例如:8,3,7

示例输入

1, 3, 4
0->2

示例输出

8, 3, 7

思路

维护一个哈希映射HashMap,其中存放的是依赖关系。
那么每遍历到一个任务,会存在一下两种情况,分别处理:

  1. 无依赖关系:此时可以 前面任务执行的时间 + 当前任务执行时间
  2. 有依赖关系:从Map中取出对应的依赖关系, 判断其依赖任务是否已经完成:
    ①如果已完成,那么可以前面任务执行的时间 + 当前任务执行时间
    ②如果依赖任务没有完成,那么跳过该任务,判断下一个任务。

注意:在遍历任务数组的时候,可以对下标采用取余的方法来访问数组,这样可以达到循环访问任务数组,然后额外维护一个变量,用以记录任务执行的个数,当任务执行的个数达到任务数组的长度,即表示任务全都完成,结束循环。

示例代码

	// 输入的处理均省略
	// map用来记录依赖关系,依赖关系可能是多重依赖
	Map<Integer, ArrayList<Integer>> map = new HashMap<>();
            int compete = 0;   //记录任务执行了多少个
            int tmp = 0;    //记录上一个任务执行完的时间
            int[] res = new int[num];   //结果数组
            while (compete != num) {
                for (int i = 0; i < num; i++) {
                    if (compete == num) {
                        break;
                    }
                    if (res[i] == 0) {//如果当前任务没有执行
                        if (!map.containsKey(i)) {//先判断是否存在依赖关系,
                            // 如果没有依赖关系就用任务本身执行的时间+前面任务执行的时间
                            res[i] = arr[i] + tmp;
                            tmp = res[i]; // 记录已经执行完毕的任务的时间
                            compete++;//执行次数加1,作为判断退出循环的条件
                        } else {
                            //如果存在依赖关系,先取出map中的值,也就是包含依赖关系的ArrayList
                            ArrayList<Integer> Depend = map.get(i);
                            //判断其前置任务是否完成
                            boolean flag = false;
                            for (Integer depend : Depend) {
                                //对于每一个依赖任务,判断它是否已经执行
                                if (res[depend] == 0) {//如果依赖任务没有执行
                                    flag = true;//flag置1
                                    break;
                                }
                            }
                            if (!flag) {
                                //如果依赖任务执行完毕,即当前任务时间+前面任务执行的时间
                                res[i] = arr[i] + tmp;
                                tmp = res[i];   //前面任务执行的时间
                                compete++;  //任务完成+1
                            }
                        }
                    }
                }
            }

题目三

到香港旅游,最后一站决定去迪士尼乐园打卡,因为返程机票已经订好,所以我们必须在剩余可游玩时间分钟内完成游玩,才能不耽误行程,请你为我们设计一条最佳游玩线路,选择规则如下:

  1. 游玩总时长不超过t,但最接近 t;
  2. 游玩时不想走回头路,仅向右或向下两个方向,畅玩到出口。

乐园被划分为一个 row * col 的方格区域地图,在每个方格区域上,标注了游玩的最佳时长,从入园口 [0,0] 出发,选定最佳游玩线路,一路畅玩到出口 [row-1, col-1]。

输入描述

首行输入以单个空格分割的三个正整数 rowcol 以及 t,row代表地图行数(0 < row ≤13), col代表地图列数(0 < col ≤ 13),t代表剩余可游玩时间(0 < t ≤ 600) ;

输出描述

最佳游玩线路游玩总时长,若不存在,请输出-1。

示例输入

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

示例输出

30

思路

使用深度优先搜索向右、向下遍历即可,因为不会走回头路,所以不需要回溯。
使用两个方向数组,向右走:{0,1},向下走{1,0}。
需要注意判断边界条件,以及中途如果所耗时间已超可游玩时间,终止递归。

示例代码

	public static int ans = -1;//定义一个全局变量,用来保存有效游玩路径的最大时间
    public static void playPath(){
    	// 输入格式的处理省略, 使用案例输入作为初始数据
        int time = 30, row = 5, col = 5;
        int x = 0, y = 0;	//起点的xy坐标
        //这个数组保存各个游戏的游玩时间
        int[][] play = new int[row][col]{
        		{3,5,4,2,3},
				{4,5,3,4,3},
				{4,3,5,3,2},
				{2,5,3,3,5},
				{5,3,4,4,1}
		};

        dfs(play, 0, 0, row, col, 0, time);
        return ans;
    }

    public static void dfs(int[][] play, int x, int y, int row, int col,int t, int time){
    	//定义移动数组,如果已经游玩过的则为true
        int[] right = new int[]{0, 1}; 	//向右移动
        int[] down = new int[]{1, 0};    //向下移动
        
        t += play[x][y];
        if(x == row - 1 && y == col - 1 && t <= time){
            ans = Math.max(ans, t);
        }else{
            int xr = x + right[0];
            int yr = y + right[1];
            if(xr < row && yr < col){
                dfs(play, xr, yr, row, col, t, time);
            }
            int xd = x + down[0];
            int yd = y + down[1];
            if(xd < row && yd < col){
                dfs(play, xd, yd, row, col, t, time);
            }
        }
    }
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值