如何在Java数字可能的求和计算中去除重复值?
嘿,这个问题我之前也碰到过!因为你的输入列表里有重复的数值(比如两个0.05),递归遍历的时候会产生完全一样的求和路径,自然就会出现重复的结果。下面给你几个实用的解决思路:
方案1:用Set替代List存储结果(最直接)
最省心的办法就是把存储结果的容器从ArrayList换成HashSet——Set的核心特性就是自动去重,完全不需要自己写额外的判断逻辑。
修改你的代码非常简单:
import java.util.ArrayList; import java.util.HashSet; import java.util.Set; public class Testing { public static void main(String[] args) { ArrayList<Double> valid = new ArrayList<Double>(); Set<Double> result = new HashSet<Double>(); // 替换成Set valid.add(0.05); valid.add(0.05); valid.add(0.1); getSum(valid, result, 0, 0); System.out.println(result); // 输出就是去重后的结果 // 如果后续需要转回ArrayList: // ArrayList<Double> uniqueResult = new ArrayList<>(result); } public static void getSum(ArrayList<Double> valid, Set<Double> result, int start, double sum) { if (valid.size() == start) { result.add(sum); return; } // 选择当前元素加入求和 getSum(valid, result, start + 1, sum + valid.get(start)); // 不选择当前元素加入求和 getSum(valid, result, start + 1, sum); } }
⚠️ 小提醒:因为你用的是Double类型,浮点数的精度问题可能会导致一些你认为相同的数值被误判为不同(比如0.1+0.05和0.05+0.1理论上相等,但浮点数计算可能产生微小差异)。如果你的场景对精度要求高,建议用BigDecimal代替Double。
方案2:递归过程中跳过重复元素(从源头避免重复)
如果你的输入数据量比较大,用Set去重可能会有性能开销,那可以在递归阶段就跳过重复元素,从根源上不生成重复的求和结果。具体步骤是:
- 先对输入的
valid列表排序; - 在递归时,判断当前元素是否和前一个元素相同,如果相同且前一个元素没有被选中,就跳过当前分支,避免重复计算。
修改后的代码示例:
import java.util.ArrayList; import java.util.Collections; public class Testing { public static void main(String[] args) { ArrayList<Double> valid = new ArrayList<Double>(); ArrayList<Double> result = new ArrayList<Double>(); valid.add(0.05); valid.add(0.05); valid.add(0.1); Collections.sort(valid); // 先排序,让重复元素相邻 getSum(valid, result, 0, 0, false); System.out.println(result); } // 新增prevSelected参数:标记前一个元素是否被选中,用来判断是否跳过重复分支 public static void getSum(ArrayList<Double> valid, ArrayList<Double> result, int start, double sum, boolean prevSelected) { if (valid.size() == start) { result.add(sum); return; } // 情况1:不选择当前元素 // 如果当前元素和前一个相同,且前一个元素没被选中,说明这个分支已经被前一个重复元素处理过了,直接跳过 if (!(start > 0 && valid.get(start).equals(valid.get(start-1)) && !prevSelected)) { getSum(valid, result, start + 1, sum, false); } // 情况2:选择当前元素 getSum(valid, result, start + 1, sum + valid.get(start), true); } }
这个方案的优势是不会生成冗余的重复结果,节省了后续去重的开销,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者Raymo111
相关产品推荐
相关产品推荐

