字节跳动 Byte Camp-算法第一轮

因为比较菜,当时做的时候也没有100%ac,然后我事后又改进的,有不当的地方欢迎指正。

Question #1

小明在北京游玩,有n个景点,第i个景点的满意度为a[i],规定景点i与景点j之间的距离为j-i(j>i)。因为时间有限,小明只能去两个景点,则两个景点的总满意度为a[i]+a[j]+i-j。问,给定一个数组,求最大的总满意度。

输入:

第一行:景点数目n

第二行:n个数字代表满意度

输出:

最大的总满意度

输入范例:

7

1 3 3 5 2 1 4

输出: 

7

分析一波:时间复杂度肯定是需要O(n)的啊,啥都不说了,都在代码里了。时间复杂度O(n),空间复杂度O(1)。

def f(a, n):
    # 记录当前的最大满意度得分
    max_s = a[0] + a[1]
    # 记录当前去掉距离下一个景点(index=2)后的最大满意度景点
    max_v = a[0]-2 if a[0]-2 > a[1]-1 else a[1]-1
    # 每次扫描下一个景点,都要对之前的具有最大满意度的景点(max_v)减去一个距离惩罚
    # 每次可以威胁到之前最大满意度得分(max_s)的,只有max_v与max_s的加和
    for i in range(2, n):
        if max_v + a[i] > max_s:
            max_s = max_v + a[i]
        # 若当前的景点满意度超过之前最大的满意度max_v,则更新max_v;并在下一次循环前,减去距离惩罚
        max_v = a[i]-1 if a[i] > max_v else max_v-1
    return max_s

Question #2

给定一个矩阵,有0和1两种数字,规定对于位置(i,j)为1时,它与它的左上方、上方、右上方、左边、右边、左下方、下方、右下方的1是连通的,求对于给定矩阵的最大连通区域的个数。

输入:

第一行:矩阵的形状m、n

接下来m行,每行包括n个数字(0或1)

输出:

最大连通区域的个数

输入范例:

3 3

0 1 0

1 0 0

1 0 1

输出: 

2

分析一波:时间复杂度为O(m\cdot\ n\cdot k),其中k为连通区域的个数,空间复杂度为O(K)。

import sys


def f(mat, m, n):
    # 用于记录当前连通区域,下标i代表连通区域,name[i]代表区域i实际所属的真实区域
    name = [0]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if mat[i][j] == 1:
                v = []
                index = []
                # 只搜索与之可达的前边的4个位置(只看前边:左上、上、右上、左)
                if mat[i - 1][j - 1] != 0:
                    v.append(name[mat[i - 1][j - 1]])
                    index.append(mat[i - 1][j - 1])
                if mat[i - 1][j] != 0:
                    v.append(name[mat[i - 1][j]])
                    index.append(mat[i - 1][j])
                if mat[i - 1][j + 1] != 0:
                    v.append(name[mat[i - 1][j + 1]])
                    index.append(mat[i - 1][j + 1])
                if mat[i][j - 1] != 0:
                    v.append(name[mat[i][j - 1]])
                    index.append(mat[i][j - 1])
                # 发现一个新的区域(其前四个位置均为0),则在name中添加一个区域,且将该位置的值从1改为区域名字的值
                if len(v) == 0:
                    mat[i][j] = len(name)
                    name.append(len(name))
                else:
                    # 若当前位置与相连的四个位置中,包含多个区域名称,则合并所有的区域为同一名称,且将该位置的值从1改为区域名字的值
                    for k in range(len(v)):
                        if k == 0:
                            mat[i][j] = v[0]
                            continue
                        else:
                            for name_index in range(len(name)):
                                if name[name_index] == v[k]:
                                    name[name_index] = v[0]
    # print(name)
    # print(mat)
    return len(set(name)) - 1


if __name__ == "__main__":
    while True:
        # 读取第一行的n
        num_line = sys.stdin.readline().strip()
        m = int(num_line.split()[0])
        n = int(num_line.split()[1])
        # print(m, n)
        mat = []
        # 在矩阵的外层,加一圈0,方便边界处理,又对结果没有影响
        zero = [0 for _ in range(n + 2)]
        mat.append(zero)
        for i in range(m):
            line = sys.stdin.readline().strip()
            # 把每一行的数字分隔后转化成int列表
            values = [0]
            for x in line.split():
                values.append(int(x))
            values.append(0)
            mat.append(values)
        mat.append(zero)
        print(f(mat, m, n))

Question #3

给定一个字符串,现在,%前一位的数字n,代表将%与#之间的字符重复n次。输出最终的结果字符串。

输入:

字符串

输出:

结果字符串

输入范例:

3%g2%n##

输出: 

gnngnngnn

分析一波:占位。

import sys


def f(line):
    if len(line) == 0:
        return ''
    res = ''
    index = []
    op = []
    str = ''
    new_line = line[2: -1]
    # print(new_line)
    for k in range(len(new_line)):
        if new_line[k] == '%':
            op.append('%')
            index.append(k-1)
        elif new_line[k] == '#' and len(op) == 1:
            str += f(new_line[index[-1]: k+1])
            op.pop(-1)
            index.pop(-1)
        elif new_line[k] == '#':
            op.pop(-1)
            index.pop(-1)
        elif len(op) == 0 and (new_line[k] <= '0' or new_line[k] >= '9'):
            str += new_line[k]
        # print(new_line[k])
    for i in range(int(line[0])):
        res += str
    return res


if __name__ == "__main__":
    line = list(sys.stdin.readline().strip())
    # line = ['3', '%', 'g', '2', '%', 'n', '#', '#']
    print(f(line))

Question #4

有一棵树,对于节点i,i/2为它的父节点,且节点i处有a[i]个房间,树的边是无向边,且长度均为1。现在有m只松鼠,对于松鼠j,其在树上的初始位置为b[j],求所有的松鼠都找到自己的独立房间所使用最少总步数是多少?

你可能感兴趣的:(刷题)