字节跳动青训营刷题笔记1 | 豆包MarsCode AI刷题

128 阅读2分钟

奇妙货币交易问题

难度:简单

样例测试拼写错误

首先代码中的样例测试是“Yes”,而提交测试的话是“YES”,这个小问题在很多题目中均出现了,注意一下即可。

问题分析

在一次交易中,每种面值的货币使用次数(买家和卖家合计)不能超过两次。这意味着我们需要找到一组整数 aia_ibib_i,满足以下条件:

  • 0ai20 \leq a_i \leq 2(买家支付的第 i 种面值货币数量)
  • 0bi20 \leq b_i \leq 2(卖家找零的第 i 种面值货币数量)
  • ai+bi2a_i + b_i \leq 2(总使用次数不超过两次)
  • i(aibi)×Vi=W(交易金额)\sum_{i} (a_i - b_i) \times V^i = W(交易金额)

所以实际上可以用一个变量去表示卖家和买家使用某一种面值的次数

算法步骤

  1. 初始化变量
    • 设置一个循环,当 W 不为零时继续处理。
  2. 循环处理金额 W
    • 在每次循环中,计算当前位的余数:remainder = W % V
    • 检查这个余数的值。
    • 从0次幂开始按位去判断能否满足使用次数
  3. 检查余数并进行调整
    • 如果 remainder > 2
      • 说明当前位所需的纸币数量超过了 2,不能直接使用。需要调整。
      • remainder 调整为 remainder - V,这表示向上借用一张更高面值的纸币。
      • 更新 W:W = (W - remainder) // V,去掉当前位的贡献,准备处理下一位。
    • 如果 remainder < -2
      • 说明即使调整后仍然不符合条件,直接返回 "NO"。
    • Else 更新 W:使用整数除法更新 W:W = W // V,去掉已经处理的位,进入下一位。
  4. 判断当前位的纸币需求是否超出了允许的最大限制
    • 如果 abs(remainder) > 2
      • 说明当前位所需的纸币数量超过了 2,不符合条件,直接返回 "NO"。
  • 算法核心:通过调整余数和更新金额,确保每个位的净使用次数在 −2 到 222 之间。

  • 交易规则:每种面值的货币总使用次数不超过 2 次。

代码

def solution(V, W):
    while W != 0:
        remainder = W % V
        if remainder > 2:
            remainder -= V
            W = (W - remainder) // V
        elif remainder < -2:
            return "NO"
        else:
            W = W // V
        if abs(remainder) > 2:
            return "NO"
    return "YES"

问题

当提交测试时,报错。 在测试用例为:V=1,W=13时,应该输出“YES”,而现在代码输出的是“NO”。

然后V=1这个特殊情况引起了我的注意。我发现我最初忽略了一点是:面值的数值可以相同(1的n次幂),但是本质上他的面值是不同的,也就是说当V=1时,对于任意整数 W,都可以找到满足条件的组合。因此,直接返回 "YES"

 if V == 1:
        return "YES"