腾讯2019年暑期实习生招聘提前批在线笔试技术研究和数据分析方向

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kabuto_hui/article/details/88541781

  前段时间参加了腾讯2019年暑期实习生招聘提前批技术研究和数据分析方向的笔试,上来就直接是5道编程题,当时做出来三道半,且还没有完全通过测试用例。

  所以下来之后又详细的研究了一番。发现其实题没有想象中的那么难,只不过在当时紧张的情况下,思维受到了一些限制。这个仓库存放了我关于这5道题的解法。代码我放在我的github上了,有兴趣的同学可以Clone到本地。

如果有什么问题,欢迎交流:[email protected]


  1. 在一场比赛中有n个检查点,比赛要求到达n-1个检查点即可,这些检查点排列在x轴上,位置分别为x1,x2,…,xn,且允许以任意顺序访问检查点。比赛的开始位置为a,求完成比赛所经过的最小距离。

【输入描述:】
输入包含两行
第一行为两个参数n,a,其中1 <= n <= 100000, -1000000 <= a <= 1000000
第二行为n个整数:x1,x2,…,xn(-1000000 <= xn <= 1000000)

【输出描述:】
输出一个整数

输入:
3 10
1 7 12

输出:
7

解题思路:】因为数据是一维的,我们可以先将这些点进行排序。然后判断开始位置距离两端的距离,距离最远的检查点就不去了,去掉这个点。再判断开始点到剩下的两个端点的距离,从最短的开始访问,得到的结果一定是最短的。再考虑到边界情况:这个开始位置在所有检查点的两侧。

def minDistance(l1, l2):

    n, x0 = l1[0], l1[1]
    point = l2

    point_sorted = sorted(point)

    if x0 < point_sorted[0]:
        return point_sorted[-1] - x0
    elif x0 > point_sorted[-1]:
        return x0 - point_sorted[0]
    else:
        # 判断x0与左右两个端点之间的距离
        l = x0 - point_sorted[0]
        r = point_sorted[-1] - x0
        if l > r: # 如果左边大于右边,则去掉第一个值
            return min(r, x0 - point_sorted[1]) + point_sorted[-1] - point_sorted[1]
        else:
            return min(l, point_sorted[-2] - x0) + point_sorted[-2] - point_sorted[0]


if __name__ == '__main__':
    test1 = {'l1': [3, 10], 'l2': [1, 7, 12], 'result': 7}
    test2 = {'l1': [3, 14], 'l2': [1, 7, 12], 'result': 13}
    test3 = {'l1': [3, 0], 'l2': [1, 7, 12], 'result': 12}

    test = [test1, test2, test3]

    count = 0

    for t in test:
        if minDistance(t['l1'], t['l2']) == t['result']:
            count += 1
        else:
            print('l1:', t['l1'], '\nl2:', t['l2'], '\nOutput:', minDistance(t['l1'], t['l2']), '\nExpect:', t['result'])

    print('Case通过率:', count*100 / len(test), '%')


  1. 小Q有一叠纸牌,一共有n张,从上往下依次编号为1~n。现在小Q要进行以下重复操作:把位于顶端的牌扔掉,把新的顶端的牌放到这叠牌的底部。小Q会一直操作到只剩下一张牌为止,小Q想知道每次扔掉的牌的编号。

【输入描述】
一个数字n, 1 <= n <= 1000000

【输出描述】
n个空格间隔的整数,表示每次丢掉的纸牌编号

输入:
7

输出:
1 3 5 7 4 2 6

解题思路:】这道题比较容易,直接模拟丢牌的过程就好:

def printNum(n):

    num = [i for i in range(1, n+1)]

    while n > 1:
        print(num[0], '', end='')
        num = num[2:] + [num[1]]
        n -= 1
    print(num[0])

if __name__ == '__main__':
    printNum(11)


  1. 小Q正在爬一座宝塔,宝塔共有n层,每层之间的净高不同,所以小Q爬过每层的时间也不同。如果某一层的高度为x,那么小Q爬的时间也是x。
    小Q还会使用一种魔法,每次可以让他向上跳一层或者两层,但是每次跳完之后,小Q都将用尽魔法,需要爬过至少一层之后才能再次跳跃。最后也可以跳到塔外,即超过塔高,就是不消耗时间的。
    小Q希望能用最短的时间爬到塔顶,希望你告诉他最短时间是多少。

【输入描述】
第一行一个数n,表示塔的层数。(n <= 10000)
接下来的每一行表示一个数h(1 <= h <= 100),表示从下往上每层的高度:

输入:
5
3
5
1
8
4

输出:
1

解题思路:】这个题同动态规划的思想,使用递归来实现。每步需要三种情况:爬一层、飞一层、飞两层。爬一层的时间是h[0],而飞了之后一定要爬一层,所以他们的时间分别为h[1]和h[2]。选择这三种情况中用时最短的方案,然后从已经到达那层开始,继续执行这个策略,直到塔剩下的层数小于3层即可:

def plan(t):
    count = 0
    if len(t) < 3:
        return 0
    if t[0] < t[1] and t[0] < t[2]: # 爬一层最好
        count += t[0]
        return count + plan(t[1:])
    if t[1] <= t[0] and t[1] < t[2]: # 跳一层最好
        count += t[1]
        return count + plan(t[2:])
    if t[2] <= t[0] and t[2] <= t[1]: # 跳两层最好
        count += t[2]
        return count + plan(t[3:])

if __name__ == '__main__':
    print(plan([3, 5, 1, 1, 1, 10, 20, 80, 20, 30, 40]))

  1. 小Q得到了一个长度为n的序列A,A中的数各不相同。对于A中的每一个数Aj,求:
    min(1 <= j < i)|Ai - Aj|,令这个式子取到的最小值的j记为Pi,若最小值不唯一,则选择使Aj较小的那个。

【输入描述】
第一行一个整数n(n <= 10^5)
第二行n个整数A1,A2,…,An(|An| <= 10^9)

【输出描述】
n-1行,每行两个整数用空格隔开。分别表示当i取2~n的时候,对应的min(1 <= j < i)|Ai - Aj|和Pi

输入:
3
1 5 3

输出:
4 1
2 1

解题思路:】这道题我直接写的两层循环,如果大家有更好的办法,请不吝赐教哇~

def printResults(n, A):

    for i in range(2, n+1):
        pi = 0
        minval = 10**9
        for j in range(1, i):
            if minval > abs(A[i-1] - A[j-1]):
                minval = abs(A[i-1] - A[j-1])
                pi = j
            elif minval == abs(A[i-1] - A[j-1]):
                if A[pi-1] > A[j-1]:
                    pi = j
        print('{0} {1}'.format(minval, pi))

if __name__ == '__main__':
    n = 4
    A = [1, 5, 3, 4]
    printResults(n, A)

  1. 一棋盘共有n行m列,任意相邻的两个格子都是不同色(黑或白),坐标(1,1)的格子为白色。>已知n和m,条件如下两步,求黑白方块的数量。
    第一步:在这块棋盘里选择一个左下角坐标(x0,y0),右上角坐标为(x1,y1),把(x1->x0+1)(y1-y0+1)的方块涂白。
    第二步:在这块棋盘里选择一个左下角坐标(x2,y2),右上角坐标为(x3,y3),把(x3->x2+1)
    (y3-y2+1)的方块涂黑。

输入描述:
第一行一个整数T,表示提问T次。
接下来3T行
第(1+3
i)行两个整数n,m,表示d第i次提问棋盘大小。
第(2+3i)行四个整数x0,y0,x1,y1,表示第i次提问涂白操作的两个坐标。
第(3+3
i)行四个整数x2,y2,x3,y3,表示第i次提问涂黑操作的两个坐标。
i<=T<=10000,>1<=x<=n<=1000000000,1<=y<=m<=1000000000,x0<=x1,y0<=y1,x2<=x3,y2<=y3;

输出表示:
共T行,每行两个整数分别表示白色和黑色方块的数量。

示例:
输入
3
1 3
1 1 1 3
1 1 1 3
3 3
1 1 2 3
2 1 3 3
3 4
2 1 2 4
1 2 3 3

输出:
0 3
3 6
4 8

解题思路:】这道我觉得是比较麻烦的,至今没有想到正常的解法。我这里用了numpy,就很方便了。用了numpy之后,生成01矩阵,然后按照给定的坐标,更改矩阵中对应区域的数据,最后统计矩阵中1的数量就是黑色方块的数量,总数减去黑色方块的数量就是白色方块的数量。
再次声明: 这道题我用了numpy,算是作弊吧,在笔试的时候,这道题根本没时间做T_T。如果大家有什么更好的办法,请一定联系我~

import numpy as np

def countBlock(filename):
    f = open(filename, 'r')
    T = int(f.readline().strip())
    q = {}
    for i in range(T):
        q['Board'] = [int(i) for i in f.readline().strip().split(' ')]
        q['first'] = [int(i) for i in f.readline().strip().split(' ')]
        q['second'] = [int(i) for i in f.readline().strip().split(' ')]

        # --------- 开始计算 ----------
        # 最开始的白块与黑块的数量
        board = np.array([i % 2 for i in range(q['Board'][0] * q['Board'][1])]).reshape(q['Board'][0], q['Board'][1])
        board[q['first'][0]-1: q['first'][2], q['first'][1]-1: q['first'][3]] = 0
        board[q['second'][0]-1: q['second'][2], q['second'][1]-1: q['second'][3]] = 1

        print("{0} {1}".format(q['Board'][0] * q['Board'][1] - board.sum(), board.sum()))
        # --------- 结束计算 ----------

if __name__ == '__main__':
    countBlock('Task05.txt')

猜你喜欢

转载自blog.csdn.net/kabuto_hui/article/details/88541781
今日推荐