2019字节跳动夏令营算法——第一次 回忆版

2个半小时,四个编程题,总结一下:

第一题

给定一个序列s,从序列中找出两个数,使得s[i]+i+s[j]-i最大,其中j>i
思路:没什么说的,经典的dp问题而已,找到包含第i个值的最大,然后最后再判断一下,见leetcode

def find(jdlist):
    length=len(jdlist)
    reslist=[None]*length
    res=0
    reslist[0]=[0,0]
    for i in range(1,length):
        fore=reslist[i-1][0]
        last=reslist[i-1][1]
        if jdlist[fore]+fore>jdlist[last]+last:
            reslist[i]=[fore,i]
        else:
            reslist[i]=[last,i]
        res=max(res,jdlist[reslist[i][0]]+reslist[i][0]+jdlist[reslist[i][1]]-reslist[i][1])
    return res

第二题

DBSCAN:
输入一个只包含0,1的二维数组,上下左右和对角相邻的1组成一块,0不形成区块,问数组中区块的个数

eg:
0 1 0
1 0 0
1 0 1

这就是2块,除了右下角的1是一块,剩下的1都是一块

def findone(numlist):
    res = {}
    for i in range(len(numlist)):
        for j in range(len(numlist[i])):
            if numlist[i][j]==1:
                res[(i,j)]=1
    return res
def dbscan(numlist):
    numlist=[[0]*(2+len(numlist[0]))]+[[0]+i+[0] for i in numlist]+[[0]*(2+len(numlist[0]))]
    check=findone(numlist)
    all=check.copy()
    times=0
    while check:
        key=list(check.keys())
        fill=key[0]
        check.pop(key[0])
        all=check.copy()
        stack=[fill]
        while stack:
            flag=stack.pop(0)
            for points in all:
                if abs(points[0]-flag[0])<=1 and abs(points[1]-flag[1])<=1:
                    stack.append(points)
                    check.pop(points)
            all=check.copy()
        times+=1
    return times

思路:
考虑的使用DBSCAN做,首先就是把原始的输入矩阵给做一个0-padding,padding=1,然后构建一个队列,寻找上下左右8个值有没有是1的,如果有的话就加入队列,有点类似于bfs的策略,离线调试通过,在线显示超出时间复杂度,有更好的策略可以提出

第三题

给定一个字符输入策略,重复#%中间的字符数次,其次数等于#/%之前的数字,其中括号可以嵌套
eg:
input:
2%nq#
3#g2%n##
output:
nqnq
gnngnngnn
思路:
这个题目有点像leetcode那个括号匹配问题,最开始考虑用栈做,匹配最近的括号,但是似乎不行,因为括号是有左右的,但是这个没有,有大佬想到可以用栈做的欢迎补充
我想到的策略是,倒序遍历,遇到数字就重复后面的字符串,然后递归去做

def get(string):
    opt=['%','#']
    num=list(map(str,list(range(1,10))))
    flag=False
    for i in range(len(string)-1,-1,-1):
        if string[i] in num:
            flag=True
            break
    if not flag:
        return string
    for j in range(i+2,len(string)):
        if string[j] in opt:
            break
    start=i+1
    end=j
    str1=string[start+1:end]
    str1=str1*int(string[i])
    string=string[:start-1]+str1+string[end+1:]
    return get(string)
print(get("3%g2%n##"))

第四题

都没顾得上看,就忙着调第二题的DBSCAN了,回头补上答案,题目如下

给定一棵n个节点树,节点1为树的根节点,对于所有其他节点i,他们的父节点编号为 f l o o r ( i 2 ) floor(\frac{i}{2}) floor(2i),在每个节点 i i i上有 a [ i ] a[i] a[i]个房间,此外树上所有边均是边长为1的无向边
树上有m只松鼠,第j只松鼠的初始位置为b[j],他们需要通过树边各自找到一个独立的房间,请为所有松鼠规划一个合适的移动方案,使得所有松鼠的移动距离最短

input:
输入三行
第一行:两个整数n,m,表示树的节点数和松鼠个数
第二行:表示n个自然数,第i个数表示节点i的房间数a[i]
第三行:包含m个正整数,其中第j个数表示松鼠j的初始位置b[j]
output:
一个整数,表示所有松鼠的移动最短距离

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值