2019【京东】【算法】【笔试】

一、选择题:

  1. 下列选项不属于串行训练的有:AdaBoost、Random Forest、XGBoost、GBDT

random foreast(随机森林)算法:各个决策树是独立的、每个决策树在样本堆里随机选一批样本,随机选一批特征进行独立训练,各个决策树之间没有啥毛线关系。

其余3个算法都是根据前一次弱学习器的误差(残差)训练下一次的弱学习器。

  1. 红黑树节点颜色
  2. 下列代码的输出是什么
  3. 已知一排序树的前序遍历和中序遍历分别是30,24,15,27,29,46和15,27,29,30,46,问平衡后的平衡二叉树的后序遍历是什么
  4. 下列哪个算法较好避免了样本不平衡问题
  5. 已知int为4字节,unsigned char为1字节,问下列代码中offset=?
  6. 核化线性降维、流行学习。

二、编程题

1.消消乐

        玩儿过消消乐游戏吗?给定一个二维数组,其中的数字属于(0~4]。一个数字与其上/下/左/右相同时,称为连通。当有三个数字连通时,可消灭,并且消灭时会同时消灭所有连通数字。消灭后,上面的数字向下掉落。不同的消灭顺序会导致不同的结果。求给定数组,消灭连通数字,最后剩余数字最少的情况有几个数字?

例:

num = [[3, 1, 2, 1, 1],
       [1, 1, 1, 1, 3],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [3, 1, 2, 2, 2]]

思路:

        由于每步消灭不同的数字会导致结果不同,所以此题为动态规划思想,即计算每种数字消灭方式到最后剩余的最少数字个数。(比如上例,先消灭1后消灭2,会剩余3个3;先消灭2后消灭1,会剩余3个3和1个2一共4个数字。取最少的情况,所以上例的答案是3)

步骤:

  • 计算当前情况下可以消灭哪些数字
  • 递归计算每种情况下最后剩余的最少数字个数

解题过程:

先写主函数:

print(min_step(num))
# min_step()函数用来求最后剩余的最少数字个数

so easy~

再写min_step(num)函数:

def min_step(num):
    # 写一个函数find_lt(),返回所有可消灭数字的位置
    # 比如在此例中,返回[[0, 1], [4, 2]], 分别是数字1和2的连通区域的某位置
    list_lt = find_lt(num)

    # 如果无可消除数字,返回当前所有数字的个数
    if len(list_lt) == 0:
        return int(np.count_nonzero(num))

    # 分别计算最先消除某数字时,最终剩余的最少数字个数
    m = []
    for i in list_lt:
        # 消除第i个连通区域数字
        liantong(num, i[0], i[1])
        # 掉落函数
        num = drop(num)
        n = num.copy()
        # 计算当前情况下的最终剩余的最少数字个数
        m.append(min_step(n))
    # 输出最小值
    return min(m)

可以看到,上面的代码任需要三个函数,即查找有哪些可消灭数字的find_lt(num)、消灭数字的liantong(num, i, j)函数和掉落函数drop(num)。

 

查找有哪些可消灭数字的find_lt(num):

def find_lt(num):
    n = num.copy()
    result = []
    for i in range(len(n)):
        for j in range(len(n[0])):
            if n[i][j] == 0:
                continue
            if liantong(n, i, j) > 2:
                result.append([i, j])
    return result

消灭数字函数:

def liantong(n, i, j):
    k = n[i][j]
    n[i][j] = 0
    v = []
    v.append([i, j])
    re = 1
    while len(v) != 0:
        # downw
        if i < len(n)-1 and n[i+1][j] == k:
            i += 1
            re += 1
            n[i][j] = 0
            v.append([i, j])
            continue
        # right
        if j < len(n[0])-1 and n[i][j+1] == k:
            j += 1
            re += 1
            n[i][j] = 0
            v.append([i, j])
            continue
        # up
        if i > 0 and n[i-1][j] == k:
            i -= 1
            re += 1
            n[i][j] = 0
            v.append([i, j])
            continue
        # left
        if j > 0 and n[i][j-1] == k:
            j -= 1
            re += 1
            n[i][j] = 0
            v.append([i, j])
            continue
        i, j = v.pop()
    return re

 

 

掉落函数drop(num):

def drop(num):
    for j in range(len(num[0])):
        slow = len(num) -1
        while num[slow][j] != 0 and slow >= 0:
            slow -= 1
        fast = slow
        while fast >= 0:
            if num[fast][j] == 0 or fast == slow:
                fast -= 1
                continue
            num[slow][j] = num[fast][j]
            num[fast][j] = 0
            slow -= 1
            fast -= 1
    return num

 

你可能感兴趣的:(笔试面试)