题解:字节跳动-编程题2

编程题2

http://www.nowcoder.com/questionTerminal/1aeba6ba677949249aba82d81edc3fea

同志们想复杂了,用的方法既满又难写,实际上解法还是很简单的。
注意这道题有一个限制:数字都在[0, 100]的范围内,这其实可以拆解为两点:
1.值非负,这决定了我们的算法
2.值小与100,这省了我们很多事,对笔试非常友好。

注意看目标函数:区间中的最小数 * 区间所有数
一个非常自然的想法是我们从小到大遍历数值,这样“区间的最小数”就确定了。
然后我们考虑区间有多大,显然,由于值非负,区间等于:[向左直到遇到已经插入的点,向右直到遇到已经插入的点]
由于我们是从小到大添加的数,那么实际上就是找:最大的比他坐标小的分割点,最小的比它坐标大的分割点,这是典型的平衡二叉树。时间复杂带图片说明
但是,平衡二叉树对于python而言是不现实的,幸亏题目限制了只有100个值,允许我们进行100次线性扫描。时间复杂度图片说明
故:

n=int(input())
inp=[int(x) for x in input().split()]
buckets=[ [] for i in range(101)] ## buckets[value]保存了所有值为value的点
sm=[0] ## sm是用来计算区间和的 sum(inp[a:b])=sm[b]-sm[a]
for i in range(len(inp)):
    sm.append(sm[-1]+inp[i])
    buckets[inp[i]].append(i)
sm.append(1E1000)
ans=0
pat=[-1,len(inp)] ## 保存已经添加的分割点
for bid,b in enumerate(buckets):
    b.sort()
    itr=0
    for p in b:
        #寻找区间的两端
        while p>=pat[itr]:
            itr+=1
        ans=max(ans,bid*( sm[pat[itr]] - sm[pat[itr-1]+1]    ))
    ## 将新的分割点加入pat(tern)数组
    pat=sorted(pat+b) ## 原则上应当用O(n)的方式合并两个有序数组,我这里懒了
print(ans)
全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务