给定正整数A求元素为3的幂且和为A的最短数组,是否有更优解法?
现有代码问题分析
你给出的原有实现逻辑是基于三进制分解,每一位的数值对应3^i的使用次数,在仅允许使用正3的幂的前提下,这个思路是对的,但存在两个可优化的问题:
- 精度风险:使用
Math.pow(3, i)计算3的幂,double类型的精度限制会导致大指数的计算结果出错。 - 冗余循环:内层遍历j的逻辑可以简化,不需要额外变量控制循环次数。
更优实现(仅正3的幂场景)
优化思路:
- 预先累加计算3的幂,避免浮点数精度问题
- 去掉冗余的内层控制变量,直接按位数值添加对应次数的元素
- 不需要额外存储完整的三进制数组,可以边取余边处理,减少内存开销
优化后代码:
public static int[] getSolve(int A) { List<Integer> res = new ArrayList<>(); int pow3 = 1; // 初始为3^0,每次循环乘3得到下一个幂 while (A > 0) { int r = A % 3; for (int i = 0; i < r; i++) { res.add(pow3); } A = A / 3; pow3 *= 3; } return res.stream().mapToInt(Integer::intValue).toArray(); }
延伸:允许正负3的幂的最短实现
如果题目允许数组元素为负的3的幂(即可以用减法凑数),可以得到更短的数组。核心思路是三进制进位优化:遇到某一位余数为2时,将其转为-1并向上一位进1,这样每一位最多只有1个元素,数组长度最短。
比如A=8,原三进制是22,原有实现返回[1,1,3,3]长度为4,优化后用9 -1,返回[9, -1]长度仅为2。
对应实现代码:
public static int[] getSolveShortest(int A) { List<Integer> res = new ArrayList<>(); int pow3 = 1; while (A != 0) { int r = A % 3; if (r == 2) { // 余数为2,转成-1,加1到高位 res.add(-pow3); A += 1; } else if (r == 1) { res.add(pow3); } A /= 3; pow3 *= 3; } return res.stream().mapToInt(Integer::intValue).toArray(); }
内容的提问来源于stack exchange,提问作者Java Carzy
相关产品推荐
相关产品推荐

