You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现基数转换循环算法 本地正确但测试不通过排查

问题背景

本题为基数转换类迭代算法题,核心规则如下:

  • 初始输入为基数b下、长度为k的非负整数minion ID n(输入格式为字符串)
  • 构造两个长度为k的整数x、y:x由n的各位数字降序排列得到,y由n的各位数字升序排列得到
  • 计算z = x - y,若z长度不足k则补充前导零,维持长度为k
  • 将z赋值为新的n,返回上一步重复迭代
    迭代最终必然进入固定循环:
    • 示例1:n=210022、k=6、b=3时,最终进入长度为3的循环[210111, 122221, 102212]
    • 示例2:n=1211、k=4、b=10时,迭代到6174后进入固定值循环(循环长度为1)
      题目要求编写函数solution(n, b),返回迭代最终进入的循环长度,若收敛到固定值(如0)则返回1。
原实现代码
def solution(n, b): #n(num): str, b(base): int
    #Your code here
    num = n
    k = len(n)
    
    resList = []
    resIdx = 0
    
    loopFlag = True
    
    while loopFlag:
        numX = "".join(x for x in sorted(num, reverse=True))
        numY = "".join(y for y in sorted(num))
        
        xBaseTen, yBaseTen = getBaseTen(numX, b), getBaseTen(numY, b)
        xMinusY = xBaseTen - yBaseTen
        num = getBaseB(xMinusY, b, k)
        
        resListLen = len(resList)
        for i in range(resListLen - 1, -1, -1):
            if resList[i] == num:
                loopFlag = False
                resIdx = resListLen - i
                break

        if loopFlag:
            resList.append(num)
            
        if num == 0:
            resIdx = 1
            break
    return resIdx

def getBaseTen(n, b): #n(number): str, b(base): int -> int
    nBaseTenRes = 0
    
    n = str(int(n)) # Shave prepending zeroes
    length = len(n) - 1
    
    for i in range(length + 1):
        nBaseTenRes += int(n[i]) * pow(b, length - i)
    
    return nBaseTenRes

def getBaseB(n, b, k): #(number): int, b(base): int, k:(len): int -> str
    res = ""
    r = 0 # Remainder
    
    nCopy = n
    while nCopy > 0:
        r = nCopy % b
        nCopy = floor(nCopy / b)
        
        res += str(r)
        
    res = res[::-1]
    
    resPrependZeroesLen = k - len(res)
    if resPrependZeroesLen > 0:
        for i in range(resPrependZeroesLen):
            res = "0" + res
    
    return res
问题现象

本地运行测试用例('1211', 10)返回1、('210022', 3)返回3,结果符合预期,但提交评测时这两个用例无法通过,不确定故障原因是算法逻辑错误,还是触发了时间限制。

故障根因

不属于时间超限问题,是代码存在3个明确的语法/逻辑错误,评测环境下会直接报错或计算结果错误:

  • 语法错误:getBaseB函数中调用了floor()方法,但未从math模块导入该函数,干净运行环境下会直接抛出NameError终止执行。本地测试能跑通大概率是因为之前运行其他代码时手动导入过floor,环境残留导致问题被掩盖。
  • 逻辑错误:0值判断永远不触发。getBaseB返回的num是固定长度为k的字符串,收敛到0时返回值是"000...0"格式的全零字符串,但代码中写的if num == 0是拿字符串类型和整数0做相等判断,结果恒为False,全零收敛场景会出现死循环或长度计算错误。
  • 逻辑错误:循环检测漏判初始值。现有逻辑是计算出新num后先和历史列表比对,不重复才加入列表,但没有把初始输入n纳入检测范围,当初始输入本身属于循环节点时,会多记录无效值导致循环长度计算偏差。
    另外自行实现的getBaseTen函数存在冗余操作,Python内置int(字符串, 进制数)原生支持任意进制字符串转十进制,手动实现不仅代码冗余,多余的类型转换也会增加不必要的耗时。
修正后可通过评测的代码
from math import floor

def solution(n, b):
    current = n
    k = len(n)
    seen = []
    
    while True:
        # 生成升序、降序排列的数字串
        x = ''.join(sorted(current, reverse=True))
        y = ''.join(sorted(current))
        # 转十进制做差
        diff = int(x, b) - int(y, b)
        # 转回目标进制,补前导零到固定长度k
        if diff == 0:
            current = '0' * k
        else:
            tmp = []
            tmp_diff = diff
            while tmp_diff > 0:
                tmp.append(str(tmp_diff % b))
                tmp_diff = floor(tmp_diff / b)
            current = ''.join(reversed(tmp)).zfill(k)
        # 检测循环
        if current in seen:
            return len(seen) - seen.index(current)
        seen.append(current)

内容的提问来源于stack exchange,提问作者Daniel Chettiar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 14:57:26