阿里巴巴2021编程题(四星)十题总结(1-5)

第一题

  • 子集
    在这里插入图片描述
from math import inf
from re import A
import sys
from bisect import bisect_right
from collections import defaultdict
input = lambda: sys.stdin.readline().rstrip("\r\n")

def I():
    return input()

def II():
    return int(input())

def MI():
    return map(int, input().split())

def LI():
    return list(input().split())

def LII():
    return list(map(int, input().split()))

def GMI():
    return map(lambda x: int(x) - 1, input().split())

def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))


def solve():
    n = II()
    xs, ys = LII(), LII()
    d = [[x, y] for x, y in zip(xs, ys)]
    lst = sorted(d, key = lambda x: (x[0], -x[1]))
    def lengthOfLIS(nums):
        # lis
        # 二分 + 贪心
        # D[i]表示长度为i时最小的lis结尾元素
        D = []
        for num in nums:
            index = bisect_right(D, num)
            # 第一个先加进来
            if len(D) == 0:
                D.append(num)
                continue
            # 相等的话不能要
            if index <= len(D) and D[index - 1] == num:
                continue

            if index == len(D):
                D.append(num)    
            else:
                D[index] = num
            #print(D)
        return len(D)
    print(lengthOfLIS([y for _, y in lst]))




    

if __name__ == '__main__':
    for _ in range(II()):
        solve()

  • 这道题显然是LIS和排序,难点是如何对于同一个x只选一个y
  • 这个只需要先对x顺序排序,再对y倒序排序,然后从y的集合中选lis(严格的)
  • 这既保证了一个x对应的ys中最多只能选一个,又保证了选出来的y是严格递增的

第二题

  • 小强爱数学
    在这里插入图片描述
import sys

input = lambda: sys.stdin.readline().rstrip("\r\n")


def I():
    return input()


def II():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return list(input().split())


def LII():
    return list(map(int, input().split()))


def GMI():
    return map(lambda x: int(x) - 1, input().split())


def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))


def solve():
    a, b, n = LII()
    MOD = 10 ** 9 + 7
    if n == 1:
        print(a)
    if n == 2:
        print((a * a - 2 * b) % MOD)
    dp = [0] * n
    dp[0] = a
    dp[1] = (a * a - 2 * b) % MOD
    for i in range(2, n):
        dp[i] = dp[i - 1] * a - b * dp[i - 2]
        dp[i] %= MOD
    print(dp[-1])


if __name__ == "__main__":
    for _ in range(II()):
        solve()

  • 找到递归公式进行dp即可
  • dp[i] = dp[i - 1] * a - dp[i - 2] * b

第三题

  • 二叉树
    在这里插入图片描述
import sys

input = lambda: sys.stdin.readline().rstrip("\r\n")


def I():
    return input()


def II():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return list(input().split())


def LII():
    return list(map(int, input().split()))


def GMI():
    return map(lambda x: int(x) - 1, input().split())


def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))

MOD = 10 ** 9 + 7
def solve():
    n, m = LII()
    # dp[i][j]: 节点个数为i且高度小于等于j的方案数
    dp = [[0 for _ in range(m + 1)] for _ in range(n + 1)]
    for j in range(m + 1):
        dp[0][j] = 1
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            # 考虑左右子树
            for k in range(i):
                tmp = (dp[k][j - 1] * dp[i - 1 - k][j - 1]) % MOD
                dp[i][j] += tmp
                dp[i][j] %= MOD
    print(dp[-1][-1])
            



if __name__ == "__main__":
    for _ in range(1):
        solve()

  • dp[i][j]表示节点个数为i,高度不超过j的总方案数
  • 经典树形dp
  • 固定一个根,然后节点个数两边分配k,高度的话就是j - 1以内即可
  • 这个数也叫做卡特兰数

第四题

  • 对称飞行器
    在这里插入图片描述
from heapq import heapify, heappop, heappush
from math import inf
import sys
from collections import defaultdict, deque

input = lambda: sys.stdin.readline().rstrip("\r\n")


def I():
    return input()


def II():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return list(input().split())


def LII():
    return list(map(int, input().split()))


def GMI():
    return map(lambda x: int(x) - 1, input().split())


def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))


def solve():
    n, m = LII()
    grid = []
    for _ in range(n):
        grid.append(I())
    d = defaultdict(lambda: inf) # (x, y, t) -> minn
    sx, sy = -1, -1
    ex, ey = -1, -1
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 'S':
                sx, sy = i, j
            if grid[i][j] == 'E':
                ex, ey = i, j
    d[(sx, sy, 0)] = 0
    dq = deque([]) # (step, x, y, t)
    
    dq.append((0, sx, sy, 0))
    #heappush(pq, (0, sx, sy, 0))
    while dq:
        #print(pq)
        step, x, y, t = dq.popleft()
        if x == ex and y == ey:
            print(step)
            return
        # 四周的点
        for nx, ny in ((x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)):
            if 0 <= nx < n and 0 <= ny < m and grid[nx][ny] != '#':
                if d[(nx, ny, t)] <= step + 1:
                    continue
                d[(nx, ny, t)] = step + 1
                #heappush(pq, (step + 1, nx, ny, t))
                dq.append((step + 1, nx, ny, t))
        # 对称点
        ox, oy = n - x - 1, m - y - 1
        if grid[ox][oy] != '#' and t < 5 and d[(ox, oy, t + 1)] > step + 1:
            d[(ox, oy, t + 1)] = step + 1
            #heappush(pq, (step + 1, ox, oy, t + 1))
            dq.append((step + 1, ox, oy, t + 1))
    
    print(-1)



if __name__ == "__main__":
    for _ in range(1):
        solve()

  • 用x, y,t记录状态,每个状态有一个最小的到达时间
  • 用d记录最小到达时间,dq直接就是最小的,这里不需要pq做额外的操作

第五题

  • 知识竞赛
    在这里插入图片描述
import sys

input = lambda: sys.stdin.readline().rstrip("\r\n")


def I():
    return input()


def II():
    return int(input())


def MI():
    return map(int, input().split())


def LI():
    return list(input().split())


def LII():
    return list(map(int, input().split()))


def GMI():
    return map(lambda x: int(x) - 1, input().split())


def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))


def solve():
    n = II()
    vs = []
    for _ in range(n):
        vs.append(LII())
    # 思维题, 按abs(a - b)排好后,i < j, 则j的a和b大小就可以决定最终的答案
    # 比如j的bj < aj,那么它和前面的组合最小值一定是b, 这时只要找到前面最大的b即可
    # 对于i而言
    # 若bi < ai, 显然btot < atot
    # 若bi > ai, 由于j的差值更大,所以bj会拉小得更厉害,所以还是又btot < atot
    vs.sort(key = lambda x: abs(x[0] - x[1]))
    ans = 0
    amax, bmax = vs[0]
    for j in range(1, n):
        a, b = vs[j]
        cur = 0
        if a < b:
            cur = (a + amax) / 2
        else:
            cur = (b + bmax) / 2
        ans = max(ans, cur)
        amax = max(a, amax)
        bmax = max(b, bmax)
    print(ans)




if __name__ == "__main__":
    for _ in range(1):
        solve()

  • 为了避免较差得能力要同时受两个人的影响
  • 我们可以根据abs(a - b)进行排序
  • 比如j的bj < aj,那么它和前面的组合最小值一定是b, 这时只要找到前面最大的b即可
  • 对于i而言
  • 若bi < ai, 显然btot < atot
  • 若bi > ai, 由于j的差值更大,所以bj会拉小得更厉害,所以还是又btot < atot

总结

思维、dp、搜索的全面考核啊。。。

猜你喜欢

转载自blog.csdn.net/weixin_40986490/article/details/129735251
今日推荐