Java递归判断数能否表示为不重复3的幂之和的代码为何失效
问题根因
现有代码无法正常运行,核心是三个问题:
- 缺少递归上界终止条件:当前逻辑仅设置了
num==0、num<0两个终止分支,没有判断「当前幂次对应的3的幂已经大于剩余待凑数值」的场景,递归会持续增大power值,当3^power超过int类型最大值2^31-1时会发生数值溢出,后续计算逻辑完全错乱,轻则返回错误结果,重则直接触发栈溢出。比如测试用例num=3时,递归会一路将power增加到20以上,直到3的幂次溢出为负数才会停止。 - 浮点数计算存在精度风险:
Math.pow返回值为double类型,大数值场景下double无法精确表示所有整数,强转int时可能出现数值偏差,比如本应为整数的3的幂,转换后可能出现少1、多1的情况,直接导致计算错误。 - 主方法无结果输出:即使递归逻辑正确,main方法中仅调用了
sumPower3(num),没有打印返回值,程序运行后也看不到校验结果。
修正后可运行代码
调整幂次计算方式、补全递归终止条件即可,修正逻辑本质是校验数字的三进制表示是否仅包含0和1(每个3的幂最多出现一次,正好对应三进制每一位系数只能为0或1,不能为2):
public class Main { public static void main(String[] args) { int num = 3; System.out.println(sumPower3(num)); } private static boolean sumPower3(int num) { // 从3^0=1开始递推,避免重复调用Math.pow产生精度问题 return sumPower3(num, 1); } private static boolean sumPower3(int remain, int currentPow) { // 剩余数值凑到0,说明符合规则 if(remain == 0) { return true; } // 当前3的幂已经大于剩余待凑数值,不可能组合成功,终止递归 if(currentPow > remain) { return false; } // 两个递归分支:选择当前3的幂/不选当前3的幂,任意分支可凑成目标值则返回true return sumPower3(remain - currentPow, currentPow * 3) || sumPower3(remain, currentPow * 3); } }
内容的提问来源于stack exchange,提问作者nuriel wainstein
相关产品推荐
相关产品推荐

