求N变为1的最少操作次数:Python实现代码错误排查
问题描述
给定自然数N,可对其执行以下3种操作:
- 将N减去1
- 若N为偶数,可将N除以2
- 若N可被3整除,可将N除以3
当N的值变为1时停止操作,需要计算将N变换为1所需的最少操作次数。
原有实现代码
#!/bin/python3 import math import os import random import re import sys # # Complete the 'count' function below. # # The function is expected to return an INTEGER. # The function accepts INTEGER num as parameter. # def count(num): count = 0 while num != 1: if (num % 3 ==0 ): count += 1 num = num / 3 elif((num -1) % 3 == 0): count += 2 num = (num - 1) / 3 elif (num % 2 ==0): count += 1 num = num / 2 else: num = num - 1 count += 1 return count
代码逻辑问题分析
代码存在两个核心问题,会导致部分测试用例返回错误结果:
贪心策略存在局部最优陷阱
代码采用硬编码优先级的贪心逻辑:优先执行除以3操作,只要num-1能被3整除就直接走「减1+除以3」的两步操作,其次优先执行除以2操作,最后才选减1。这种仅判断当前一步收益的逻辑没有全局视角,会在很多场景下选错路径:- 比如
num=16时,代码判断16-1=15能被3整除,会选择减1后除以3得到5,后续5变1需要3步,总步数计算为5;但实际最优路径是连续除以4次2,总步数仅为4。 - 比如
num=40时,代码判断40-1=39能被3整除,选择减1后除以3得到13,后续13变1需要4步,总步数计算为6;但实际最优路径是40→20→10→9→3→1,总步数仅为5。
本质是代码默认「凑出3的倍数马上除3」的收益最高,但没有考虑连续除以2、或者多做一两次减1后走除2路径的总步数可能更低。
- 比如
除法操作使用错误,存在精度风险
代码中用了浮点数除法/,Python3中该操作会返回浮点型结果,当处理的数值超过2^53(浮点数整数精确表示边界)时,会出现精度丢失,轻则结果计算错误,重则触发死循环。整数数值计算场景下应该用整数除法//返回整数结果。
这类求最少操作步数的问题不适合用硬编码规则的贪心实现,最稳妥的方案是用动态规划递推:定义
dp[i]为i变1的最少步数,递推关系为dp[i] = 1 + min( dp[i-1], dp[i//2](i为偶数时取该值), dp[i//3](i能被3整除时取该值) ),从1开始递推到目标值即可得到正确结果。
内容的提问来源于stack exchange,提问作者Vardan Danielyan
相关产品推荐
相关产品推荐

