腾讯0407实习生笔试题--技术研究与数据分析(算法)--python版

今晚做了腾讯的笔试,方向是技术研究与数据分析(我本人投的算法岗)。万万没想到还有25题不定项选择题,不定项选择题包含:数据结构,微积分,线性代数,概率论。完全没有准备,选择题基本没有会的。分数是25*3+3*20=135分。攒点人品,整理一下把编程题发上来方便后人,以后哪个大佬进腾讯了帮我内推下哈哈哈。老规矩,前面是题目,方便自己动手编程,后面是解析和代码。PS:时间统一为C/C++1秒其他2秒
第一题:小Q手上开始有一个整数N,它每一次可以对这个数做如下操作:①对当前手上所有的数减1②把所有的数拆分为两个更小的数之和。其中拆分次数要不大于k次。问小Q最少需要多少次操作才能将N完全消除。输入说明:一行两个正数n,k用空格隔开。输出说明:输出最少次数。测试用例:①5 2 -->4;②15 4 -->6。PS:本题较难理解,所以给出测试用例,个人觉得是题目表达不明确,因为我一个同学也理解错了。正确的理解(不一定正确,但是AC了,谁有更正确的想法也麻烦告知我一下)我解析的时候说明。
第二题:小Q所在的镇子有一条公路连接所有的n个村庄。有些村庄需要卖水果有些村庄需要买水果,数量用Ai表示(Ai>0说明需要卖水果,Ai<0说明需要买水果,所有的Ai之和为0)。把k个单位的水果运输到相邻的村庄需要费用为k。问所有村庄都满足买卖需求的最少费用是多少。输入说明:第一行是村庄个数,第二行是村庄需要的水果数,用空格隔开。1<=n<=10000.测试用例:5   5 -4 1 -3 1 -->9
第三题: 小Q手上有n个数,它对这些数做k次如下操作:每次输出非零的最小数,再对所有非0数减去该数值,如果所有数都为0则输出0。输入说明:第一行为n,k,用空格隔开,第二行为空格隔开的n个数。说出说明:k行,每行一个数。数1<=Ai<=10000

第一题:小Q手上开始有一个整数N,它每一次可以对这个数做如下操作:①对当前手上所有的数减1②把所有的数拆分为两个更小的数之和。其中拆分次数要不大于k次。问小Q最少需要多少次操作才能将N完全消除。输入说明:一行两个正数n,k用空格隔开。输出说明:输出最少次数。测试用例:①5 2 -->4;②15 4 -->6。

问题说明:第一题的问题在于第二个测试用例,理解方式有以下几种。第一种:最开始的理解是每一步如果选择拆分的话,k只加1。那么15=8+7=4+4+4+3=2+2+2+2+2+2+2+1。2的话需要2步,所以需要的步数是3(因为是3个=号说明擦偶偶了3步)+2=5步,而不是测试用例给的6步。第二种:如果奇数不能拆分的话(例如3=2+1,那么1不能拆分并且也不能减去两次,所以觉得题意可能是只有偶数可以用拆分),那么就是遇到奇数减1,遇到偶数除以2直到k用完。则是15-->14-->7+7-->6+6-->3+3-->2+2,最后再加上2步那么就是7步。第三种:在快要交卷的时候才想出还有最后一种可能的理解方式,就是拆分计数是拆分一个数计一次。那么15--8+7--4+4+4+3,拆分15用一次,拆分8和7用了两次,k只剩一次,因此后面不能再拆分了。4-->需要4步,那么就是2+4=6。三种方式我都实验了,第一种方式通过80%(PS:牛客上有人用这种方式AC了,还有人通过70%,只能说判题系统莫名其妙);第二种方式通过60%,第三种方式我AC了。下面附上第三种方式的代码

# -*- coding:utf8 -*-
# 技术研究与数据分析
# 15 4->6怎么来的?要么5要么7啊
# 这是正确的
nk = input().strip().split()
n = int(nk[0])
k = int(nk[1])
res = 0
cnt = 0
base = 1
while n > 2 and cnt + base <= k:
    n = (n+1) // 2
    res += 1  # 一开始忘了这步真无语
    cnt += base
    base *= 2
res += n
print(res)

第二题:小Q所在的镇子有一条公路连接所有的n个村庄。有些村庄需要卖水果有些村庄需要买水果,数量用Ai表示(Ai>0说明需要卖水果,Ai<0说明需要买水果,所有的Ai之和为0)。把k个单位的水果运输到相邻的村庄需要费用为k。问所有村庄都满足买卖需求的最少费用是多少。输入说明:第一行是村庄个数,第二行是村庄需要的水果数,用空格隔开。1<=n<=10000。测试用例:5   5 -4 1 -3 1 -->9

第二题我用的暴力法,时间复杂度是O(n2),所以是在规定时间内只通过60%。后来看了别人的C++代码,用的是O(n)的贪心方法。根据自己的理解写出python代码。先说明一下思路,不然蛮多人可能理解不了代码。以测试用例为例。

暴力法:5 -4 1 -3 -1 --> 1 0 1 -3 1接下来把最左边的1给到第一个负数-3,变为0 0 1 -2 1。再找到第一个不是0的继续上述步骤。

贪心思想:5 -4 1 -3 -1 --> 0 1 1 -3 1,因为第一个位置上的5必须经过第二个位置,所以可以认为直接把所有的都给到第二个位置,接下来再从第二个位置运输。这时候问题相当于变为了n-1个村庄的运输问题了,再按照上面的思路进行就可以了。

# -*- coding:utf8 -*-
# 技术研究与数据分析
def other(n, nums):
    res = 0
    cur = 0
    for i in range(n):
        cur += nums[i]
        res += abs(cur)
    print(res)


def mine(n, nums):
    i = 0
    res = 0
    while i < n:
        if nums[i] == 0:
            i += 1
            continue
        j = i + 1
        if nums[i] > 0:
            while j < n and nums[i] > 0:
                if -nums[i] <= nums[j] < 0:
                    res += -nums[j] * (j - i)
                    nums[i] += nums[j]
                    nums[j] = 0
                elif nums[j] < -nums[i]:
                    res += nums[i] * (j - i)
                    nums[j] += nums[i]
                    nums[i] = 0
                j += 1
        else:
            while j < n and nums[i] < 0:
                if 0 < nums[j] <= -nums[i]:
                    res += nums[j] * (j - i)
                    nums[i] += nums[j]
                    nums[j] = 0
                elif nums[j] > -nums[i]:
                    res += -nums[i] * (j - i)
                    nums[j] += nums[i]
                    nums[i] = 0
                j += 1
        i += 1
    print(res)


n = int(input())
line = input().strip().split()
nums = list(map(int, line))
other(n, nums)
mine(n, nums)

第三题: 小Q手上有n个数,它对这些数做k次如下操作:每次输出非零的最小数,再对所有非0数减去该数值,如果所有数都为0则输出0。输入说明:第一行为n,k,用空格隔开,第二行为空格隔开的n个数。说出说明:k行,每行一个数。数1<=Ai<=10000

思路:因为每次所有非0数减去最小值,如果说有相同的数,那么显然同时变为一个数,因此想到要先去重,因为要找很多次最小值,所以排序显然比每次index更方便,去重后排序是很多人都能想到的。这题不难,不过最巧的方式的话比较难想一点,代码只有几行。举例帮助理解:2 3 7 10

2 3 7 10-->2

0 1 5 8-->1

0 0 4 7-->4

0 0 0 3-->3

可以发现,2=2-0;1=3-2;4=7-3;3=10-7。也就是说,输出值等于nums[i]-nums[i-1],第一次是nums[0]-0.具体怎么回事看不懂的建议自己思考。

# -*- coding:utf8 -*-
# 技术研究与数据分析
nk = input().strip().split()
n = int(nk[0])
k = int(nk[1])
line = input().strip().split()
number = list(map(int, line))
nums = list(set(number))
nums.sort()
res = 0
# 不需要考虑第一位会不会是0,因为题目说了1<=Ai
# 如果k大于set长度,剩余的都输出0
if k <= len(nums):
    for i in range(k):
        print(nums[i]-res)
        res = nums[i]
else:
    for i in range(len(nums)):
        print(nums[i]-res)
        res = nums[i]
    for i in range(k-len(nums)):
        print(0)

 

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值