第六届字节跳动青训营第七课 | 豆包MarsCode AI 刷题

46 阅读4分钟

小E正在训练场进行射击练习,靶有10个环,靶心位于坐标**(0, 0)**。每个环对应不同的得分,靶心内(半径为1)得10分,依次向外的每个环分数减少1分。若射击点在某个半径为**i**的圆内,则得**11-i**分。如果射击点超出所有的环,则得0分。

根据给定的射击坐标**(x, y)**,请计算小E的射击得分。

测试样例

样例1:

输入:**x = 1, y = 0** 输出:**10**

样例2:

输入:**x = 1, y = 1** 输出:**9**

样例3:

输入:**x = 0, y = 5** 输出:**6**

样例4:

输入:**x = 3, y = 4** 输出:**6**

def solution(x: int, y: int) -> int:
    # write code here
    # print(11 - ((x * x) + (y * y)) ** (1/2))
    return int(11 - ((x * x) + (y * y)) ** (1/2))
    # return 0


if __name__ == '__main__':
    print(solution(1, 0) == 10)
    print(solution(1, 1) == 9)
    print(solution(0, 5) == 6)
    print(solution(3, 4) == 6)

RPC

RPC 需要解决的问题

  1. 函数映射
  2. 数据转换成字节流
  3. 网络传输

完整过程

  • IDL文件:描述接口(proto)
  • 生成代码:把IDL转换成对应语言的静态库 (protoc)
  • 编解码
  • 通信协议
  • 网络传输

RPC 带来的问题

  1. 服务宕机
  2. 网络异常,如何保证可达性
  3. 请求量突增

分层设计

数据格式

  • 语言特定的格式,java.io.Serializable 不能用于其他语言
  • 文本格式 json, xml, csv 人类可读,描述不严谨,没有模型约束,性能差
  • 二进制编码 protobuf等

TLV 编码

  • Tag:标签,也可以理解为类型
  • Lenght:长度
  • Value:值,Value 也可以是个TLV 结构

选型

  • 兼容性,添加新的字段不影响老的服务
  • 通用型,支持跨平台,跨语言
  • 性能,从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长。

协议层-概念

特殊结束符

一个特殊字符作为每个协议单元结束的标示

变长协议

以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度

关键指标

稳定性

  • 熔断
  • 限流
  • 超时控制
  • 请求成功率
    • 负载均衡
    • 重试
  • 长尾请求--传输时长超过百分之99的数据包 -- TCP99
    • Backup Request
  • 注册中间件

易用性

  • 开箱即用:合理默认参数、丰富的文档
  • 周边工具:生成代码工具、脚手架工具

扩展性

  • middleware
  • option
  • 编解码层
  • 协议层
  • 网络传输层
  • 代码生成工具插件扩展

观测性

Log、metric、tracing

内置观测性服务

高性能

企业实践

自研网络库-背景

  • 原生库无法感知连接状态 : 池中存失效连接
  • 原生库存在 goroutine 暴涨的风险

Netpoll

  • 解决无法感知连接状态问题:引入 epoll 主动监听机制,感知连接状态
  • 解决gotoutine暴涨的风险:建立gotoutine 池,复用goroutine
  • 提升性能:引入 Nocopy Buffer, 向上层提供NoCopy的调用接口,编解码层面零拷贝

网络库优化

合并部署

微服务过微,传输和序列化开销越来越大

将亲和性强的服务实例尽可能调度到同一个物理机上,远程RPC 调用优化为本地IPC调用

红包运气排行榜-问题描述

小C参与了一场抢红包的游戏,现在他想要对所有参与抢红包的人进行一次运气排名。排名规则如下:抢到的金额越多,排名越靠前;如果两个人抢到的金额相同,则按照他们抢红包的顺序进行排名。比如,如果小C和小U抢到的金额相同,但小C比小U先抢,则小C排在小U前面。

测试样例

样例1:

输入:**n = 4 ,s = ["a", "b", "c", "d"] ,x = [1, 2, 2, 1]**
输出:**['b', 'c', 'a', 'd']**

样例2:

输入:**n = 3 ,s = ["x", "y", "z"] ,x = [100, 200, 200]**
输出:**['y', 'z', 'x']**

样例3:

输入:**n = 5 ,s = ["m", "n", "o", "p", "q"] ,x = [50, 50, 30, 30, 20]**
输出:**['m', 'n', 'o', 'p', 'q']**

:::success 有的人不止抢了一次

:::

def solution(n: int, s: list, x: list) -> list:
    count = {}
    # 创建包含每个人信息的列表
    people = []
    for i in range(n):
        v = count.get(s[i], -1)
        if v == -1:
            people.append(((s[i], x[i], i)))
            count[s[i]] = len(people)-1
        else:
            people[v] = (s[i], people[v][1] + x[i], people[v][2])

    # people = [(s[i], x[i], i) for i in range(n)]

    # 按照规则排序
    people.sort(key=lambda p: (-p[1], p[2]))

    # 提取排序后的名字
    result = [p[0] for p in people]

    return result


if __name__ == '__main__':
    print(solution(4, ["a", "b", "c", "d"], [
          1, 2, 2, 1]) == ['b', 'c', 'a', 'd'])
    print(solution(3, ["x", "y", "z"], [100, 200, 200]) == ['y', 'z', 'x'])
    print(solution(5, ["m", "n", "o", "p", "q"], [
          50, 50, 30, 30, 20]) == ['m', 'n', 'o', 'p', 'q'])