华为2019年3月27日实习生笔试题及解答

3月27日做了华为笔试,3道题2小时。当时没有拍照,现在凭记忆将题目和代码叙述一遍,方便后人。前面将把三道题分别列一下,供后来者自己做。在后面说明一下自己的写法

第一题:题目说的比较复杂,读懂题意之后大致是,9个字符一组,每组的第一个字符是标志位,后面8个字符是地址。如果标志位是0,地址逆序,标志位是1地址不变。输入说明:一个字符串,有多组字符,中间没有空格。输出说明:输出最后的地址,每组地址用空格隔开,最后一个输出不需要空格。时间:C/C++1秒其他2秒

第二题:简而言之就是TSP问题。蜂巢在坐标(0,0)的位置,有五处花丛,蜜蜂从蜂巢出发,要把五处花丛的花蜜采完再回到蜂巢,最短距离是多少。输入说明:一行输入,10个数分别是五处花丛的坐标(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5),用空格隔开。输出说明:输出最短距离,距离向下取整。时间:C/C++5秒其他10秒

第三题:切水果游戏。有一个40×50的方格,里面有n(1≤n≤36)个水果,每一刀可以横切,竖切以及左斜切与右斜切四种方式。想要切完所有水果,最少需要多少刀。输入说明:第一行是说过个数n,接下来的n行是水果的横纵坐标。输出说明:输出最少需要的刀数。(PS:原题有图,这里无图解释一下切割方式,横切就是所有x相同的水果可以一刀切完,纵切就是y相同,左斜切就是x-y相同,右斜切就是x+y相同)。时间:C/C++3秒其他6秒

下面是各题做法和思路:

第一题:题目说的比较复杂,读懂题意之后大致是,9个字符一组,每组的第一个字符是标志位,后面8个字符是地址。如果标志位是0,地址逆序,标志位是1地址不变。输入说明:一个字符串,有多组字符,中间没有空格。输出说明:输出最后的地址,每组地址用空格隔开,最后一个输出不需要空格。

解答:第一题很简单,9个一组得读取,判断第一个是0还是1即可。5分钟内即可AC。

    # -*- coding:utf8 -*-
    n = int(input())
    strs = input()
    for i in range(n):
        s = strs[9*i:9*i+9]  # 9个一组得读取
        if s[0] == '0':
            s = s[1:]
            s = s[::-1]  # 逆序
        else:
            s = s[1:]
        print(s, end=' ')  # 空格输出

第二题:简而言之就是TSP问题。蜂巢在坐标(0,0)的位置,有五处花丛,蜜蜂从蜂巢出发,要把五处花丛的花蜜采完再回到蜂巢,最短距离是多少。输入说明:一行输入,10个数分别是五处花丛的坐标(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5),用空格隔开。输出说明:输出最短距离,距离向下取整。

解答:一开始就想到了全排列之后贪心算法取最小,虽然觉得方法太low了,但是让我一下子写出蚁群之类的觉得记忆模糊就很纠结。后来发现这道题给了10秒的运行时间,妥妥的决定用全排列了。思路:先用全排列的方式获取蜜蜂访问5个花丛的所有可能顺序,之后计算每个路径长度取最小。

    # -*- coding:utf8 -*-
    from math import sqrt
    line = input().strip().split()
    n = list(map(int, line))
    n = [int(i) for i in line]
    nums = [[0,0], [n[0],n[1]], [n[2],n[3]], [n[4],n[5]], [n[6],n[7]], [n[8],n[9]]]
    # 以下为插入的方式获取全排列的代码。没看过别人的,自己想到的。
    # 后来看网上说,递归获取全排列更常见,有兴趣的可以自己去搜一下。
    order = [[1]]
    for i in range(2,6):
        lens = len(order)
        j = 0
        while j < lens:
            for k in range(i-1):
                tmp = order[j][:]  #
                order.append(tmp)
                order[-1].insert(k, i)
            order[j].append(i)
            j += 1
    # 接下来是制作距离矩阵
    dist = [[0] * 6 for i in range(6)]
    for i in range(6):
        for j in range(6):
            if dist[i][j] == 0:
                dist[i][j] = sqrt((nums[i][0]-nums[j][0])**2 + (nums[i][1]-nums[j][1])**2)
            else:
                dist[i][j] = dist[j][i]
    # 贪心算法取最小
    minVal = 0
    for path in order:
        sums = dist[0][path[0]]
        for i in range(4):
            sums += dist[path[i]][path[i+1]]
        sums += dist[path[4]][0]
        if minVal > sums or minVal == 0:
            minVal = sums
    print(int(minVal))

第三题:切水果游戏。有一个40×50的方格,里面有n(1≤n≤36)个水果,每一刀可以横切,竖切以及左斜切与右斜切四种方式。想要切完所有水果,最少需要多少刀。输入说明:第一行是说过个数n,接下来的n行是水果的横纵坐标。输出说明:输出最少需要的刀数。(PS:原题有图,这里无图解释一下切割方式,横切就是所有x相同的水果可以一刀切完,纵切就是y相同,左斜切就是x-y相同,右斜切就是x+y相同)。时间:C/C++3秒其他6秒。

解答:当时用的贪心算法,只通过了70%,后来想到了动态规划算法,虽然没试过但是个人感觉应该可以AC。和LeetCode零钱兑换问题差不多的思路。

    # -*- coding:utf8 -*-
    # 40 * 50的方格
    from random import randint
    # 动态规划算法。对于一个点,四种切法去除被切除的点即可获得下一次的点集。加上1即可
    def dp(points):
        if len(points) <= 1:
            return len(points)
        first = points[0]
        row = [i for i in points if i[0] != first[0]]
        cntRow = dp(row)
        col = [i for i in points if i[1] != first[1]]
        cntCol = dp(col)
        left = [i for i in points if i[2] != first[2]]
        cntLeft = dp(left)
        right = [i for i in points if i[3] != first[3]]
        cntRight = dp(right)
        return 1 + min(cntRow, cntCol, cntLeft, cntRight)
     
     
    # 贪心算法。假设只能选择一种方式切,选择刀数最少的
    def greedyOne(points):
        x = [i[0] for i in points]
        y = [i[1] for i in points]
        l = [i[2] for i in points]
        r = [i[3] for i in points]
        return min(len(set(x)), len(set(y)), len(set(l)), len(set(r)))
     
     
    n = int(input())
    points = []
    for i in range(n):
        line = input().strip().split()
        x = int(line[0])
        y = int(line[1])
        l = y - x
        r = x + y
        points.append([x, y, l, r])
    '''
    # 此部分为随机获取点值,确定自己的动态规划算法是否最优
    n = 15
    for i in range(10):
        points = []
        for j in range(n):
            x = randint(0,40)
            y = randint(0,50)
            l = y - x
            r = x + y
            points.append([x, y, l, r])
        res1 = dp(points)
        res2 = greedyOne(points)
        print('dp is %d, greedy is %d'%(res1, res2))
        if res1 > res2:
            print(points)
    '''
----------
原文:https://blog.csdn.net/watermelon_learn/article/details/88902117  
 

更多福利,我总结出了很多互联网公司Java面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。可以加Java面试交流群;609840239免费领取。也欢迎各位大佬一起在群里探讨技术。

猜你喜欢

转载自blog.csdn.net/bi_zhiyi/article/details/89097807