字节跳动8.12机试五道编程题_Nelson

字节跳动8.12机试五道编程题_Nelson

第一题:

在[m,n]的矩阵中,只有1,0元素。定义相邻包括:上,下,左,右,左上,左下,右上,右下八个点,求连通区域的数量,以及最大连通区域中元素1的个数。

解法:递归回溯

Python Code:

import sys
a = sys.stdin.readline().strip().split(',')
m = int(a[0])
n = int(a[1])
d = []
num = []
pp = []
for i in range(m):
    a = sys.stdin.readline().strip().split(',')
    d.append(a)
flag = [] #记录点是否被访问过
for i in range(m):
    p = [0]*n
    flag.append(p)
############################################
def fun(d,i,j):
    if i>=m or j>=n or i<0 or j<0:
        return 0
    if d[i][j] =='0' or flag[i][j] ==1:
        return 0
    global count
    count += 1
    flag[i][j] = 1
    fun(d, i - 1, j - 1)
    fun(d, i - 1, j)
    fun(d, i - 1, j + 1)
    fun(d, i, j - 1)
    fun(d, i, j + 1)
    fun(d, i + 1, j - 1)
    fun(d, i+1, j)
    fun(d, i + 1, j + 1)
############################################
for i in range(m):
    for j in range(n):
        if d[i][j] == '1' and flag[i][j] == 0:
            count = 0
            fun(d, i, j)
            num.append(count)

print(len(num), end=',')
print(max(num))

第二题:

为了提高文本质量…求众多区间合并,相当于求多个区间的并集

思路:排序后合并

Python Code:

def fun(data):
    data = sorted(data)

    result = []
    index = 0
    for i in range(1,len(data)):
        if data[i-1][1] >= data[i][0]:
            continue
        result.append([data[index][0], data[i-1][1]])
        index = i
    result.append([data[index][0], data[i][1]])
    return result

data = [[11,12],[8,10],[1,4],[2,8]]
print(fun(data))

第三题:抽牌游戏

抽牌游戏,每张拍有(x,y),A,B分别抽,A(x)代表A手里所有牌x的和,B(x)代表B手里所有牌x的和。求A(x)==b(x)时,A(y)+B(y)的最大值,

思路:动态规划利用动态规划,维护一个数组buf[],size = 2*sum(x)+1。buf[i]存放的是A(X)-B(X)+sum(x) = i时,A(y)+B(y)的最大值。这里+sum(x)是为了保证index大于0。以sum(x) = 4 为例size=9,index= 0-8:

[0, 1, 2, 3, 4, 5, 6, 7, 8] ——–> A(X)-B(X)+sum(x)

[-4, -3, -2, -1, 0, 1, 2, 3, 4] ——–> A(X)-B(X)

所以动态维护该数组,最终输出buf[sum(x)] 代表差为0时,A(y)+B(y)的最大值。

buf[i] = max( buf[i], buf[i-x[j]], buf[i+x[j]] )

括号中:buf[i]代表x[j] A、B都不拿;buf[i-x[j]]代表 A 拿x[j];buf[i+x[j]]代表 B 拿x[j]。

Python Code:

def fun(data):
    n = len(data)
    x = []
    y = []
    for i in data:
        x.append(i[0])
        y.append(i[1])
    sum_x = sum(x)
    buf = [-float('inf')] * (2 * sum_x + 1)
    buf[sum_x] = 0
    num = len(buf)
    for i in range(n):
        b = buf.copy()
        for j in range(num):
            if j + x[i] < num:
                buf[j] = max(b[j], b[j + x[i]] + y[i])
            if j - x[i] >= 0:
                buf[j] = max(buf[j], b[j - x[i]] + y[i])
    return buf[sum_x]


a = [[3, 1], [2, 2], [1, 4], [1, 4]]
print(fun(a))

第四题:统计满足条件的区间个数

两个同样大小的数组,a,b。统计MAX(a[l,k]) < MIN(b[l,k])的总数,即是在某一段相同始末位置的子数组中,a的该子数组的最大值如果小于b的对应的子数组的最小值则计数1。

思路:对于[l , k]区间来说,随着k变大 max( a[l,k+1] )>=max( a[l,k] ),

min(b[l,k+1])<=min(b[l,k])。这两条单调的性质意味着找到最大的k,使得:

max(a[l,k]) < max(b[l,k]),计数器加(k - l + 1). 利用二分法,复杂度为O(nlog(n)).

Python Code:

def fun(a,b):
    n = len(a)
    num = 0
    for i in range(n):
        left = i
        right = n-1
        while left <= right:
            mid = left + (right - left)//2
            if max(a[i:mid+1]) >= min(b[i:mid+1]):
                right = mid - 1
            else:
                left = mid + 1
        if max(a[i:mid+1]) < min(b[i:mid+1]):
            num += mid - i + 1
        else:
            num += mid - i
    return num

a = [1,1,2,1,1,1]
b = [1,2,3,4,5,6]
print(fun(a,b))

第五题:主播问题,

贪心算法,类似于背包,在此基础上加滑动指针。复杂度O(n2)

Python Code:

def fun(data, m):
    x = []
    for item in data:
        if item[0] < item[1]:
            x.append([item[0], item[1]])
            x.append([item[0]+m, item[1]+m])
        else:
            x.append([item[0], item[1] + m])
            x.append([item[0] + m, item[1] + m + m])
    x = sorted(x, key=lambda k: k[1])
    res = 0
    for i in range(len(x)):
        num = 1
        index = i
        for j in range(i, len(x)):
            if x[j][1] - x[i][0] > m:
                break
            if x[j][0] >= x[index][1]:
                num += 1
                index = j

        if num > res:
            res = num
    return res


if __name__ == '__main__':
    data = [[0,1],[2,7],[6,9]]
    print(fun(data,10))

-另外一种方法O(n)复杂度,利用两个索引,把数据控制在一天内

def fun(data, m):
    x = []
    for item in data:
        if item[0] < item[1]:
            x.append([item[0], item[1]])
            x.append([item[0]+m, item[1]+m])
        else:
            x.append([item[0], item[1] + m])
            x.append([item[0] + m, item[1] + m + m])
    x = sorted(x, key=lambda k: k[1])
    res = 0
    num = 1
    first = 0
    index = 0
    for i in range(1,len(x)):
        if x[i][1] - x[first][0] > m:
            first += 1
            if num > res:
                res = num
            continue
        if x[i][0] >= x[index][1]:
            num += 1
            index = i
    return res

if __name__ == '__main__':
    data = [[0,5],[2,7],[3,9]]
    print(fun(data,10))

总结:

部分代码没有按照题目中的标准输入输出,只给出了核心代码。代码只测试过少量数据,如有问题,欢迎留言指正。

你可能感兴趣的:(字节跳动8.12机试五道编程题_Nelson)