2020.8.8网易算法岗笔试复盘

素数分解

数学题

买票

dp题

平分物品

现在有n个物品,每个物品都有一个价值,现在想将这些物品分给两个人,要求这两个人分到的物品价值总和相同(个数可以不同,总价值相同即可),剩下的物品就要扔掉,现在想知道最少需要扔多少价值的物品才能满足要求分给两个人。

  • 输入描述
    第一行输入n,表示物品个数
    第二行输入n个物品的价值
  • 输出描述
    最少需要扔掉多少价值的物品
  • 示例
    5
    30 60 5 15 30
    20
    解释:平分了60+30+30,丢弃了5+15,所以输出20

暴力法,时间复杂度为 O ( 3 n ) O(3^n) O(3n)

import sys
if __name__ == "__main__":
    n = int(sys.stdin.readline().strip())
    # 读取每一行
    line = sys.stdin.readline().strip()
    # 把每一行的数字分隔后转化成int列表
    data = list(map(int, line.split()))
    res = sys.maxsize

    def dfs(idx, a, b, drop):
        global res
        if idx == len(data):
            if a == b:
                res = min(res, drop)
            return
        dfs(idx+1, a+data[idx], b, drop)
        dfs(idx+1, a, b+data[idx], drop)
        dfs(idx+1, a, b, drop+data[idx])

    dfs(0, 0, 0, 0)
    print(res)

dp法,时间复杂度为 O ( n ∗ t o t a l ) O(n*total) O(ntotal) t o t a l total total是所有物品价值之和

import sys
if __name__ == "__main__":
    n = int(sys.stdin.readline().strip())
    # 读取每一行
    line = sys.stdin.readline().strip()
    # 把每一行的数字分隔后转化成int列表
    data = list(map(int, line.split()))
    total = sum(data)
    dp = [0]*(total+1)
    dp[0] = 1
    for i in range(n):
        for j in range(total, data[i]-1, -1):
            dp[j] = dp[j] | dp[j-data[i]]
    res = total
    for i in range(total, -1, -1):
        if i % 2 != 0:
            continue
        if dp[i] and dp[i//2]:
            res = total-i
            break
    print(res)

教授认可

n个教授讨论学术成果,如果教授 i i i认可教授 j j j,教授 j j j认可教授 k k k,那么可以认为教授 i i i认可教授 k k k。教授可以自己认可自己的学术成果。

  • 输入描述
    第一行输入n和m,表示n个教授,m条认可关系
    接下来m行,每一行输入认可关系<x,y>,表示教授x认可教授y
  • 输出描述
    输出互相认可的教授对有多少
  • 示例
    5 6
    1 3
    3 2
    2 1
    3 5
    5 4
    4 5
    4
    解释: 教授1,2,3互相认可,这有3对;教授4,5互相认可,这有1对。共4对。

图论之有向图寻找强连通分量,强连通分量指的是结点可以互相到达的子图。使用tarjan算法,时间复杂度为 O ( V + E ) O(V+E) O(V+E) V V V表示结点个数, E E E表示有向边个数。

from collections import defaultdict

def tarjan(node):
    global dfn, low, time, stack, res
    dfn[node] = low[node] = time
    time += 1
    stack.append(node)
    for adj_node in graph[node]:
        if dfn[adj_node] == 0:
            tarjan(adj_node)
            low[node] = min(low[node], low[adj_node])
        elif adj_node in stack:
            low[node] = min(low[node], low[adj_node])

    count = 0
    if dfn[node] == low[node]:
        while stack:
            tmp = stack.pop()
            count += 1
            if tmp == node:
                break
    if count > 1:
        res += int((count*(count-1))/2)


if __name__ == "__main__":
    # 读取每一行
    line = sys.stdin.readline().strip()
    # 把每一行的数字分隔后转化成int列表
    nm = list(map(int, line.split()))
    n, m = nm[0], nm[1]
    # 构建图
    time = 1
    dfn = [0]*(n+1)
    low = [0]*(n+1)
    stack = []
    graph = defaultdict(list)
    for i in range(m):
        # 读取每一行
        line = sys.stdin.readline().strip()
        # 把每一行的数字分隔后转化成int列表
        xy = list(map(int, line.split()))
        if xy[0] == xy[1]:
            continue
        graph[xy[0]].append(xy[1])

    res = 0
    for node in range(1, n+1):
        if dfn[node] == 0:
            tarjan(node)

    print(res)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值