Java实现查找子集和最接近π的子集及对应和值的问题求解
修改思路
你现在的核心问题是只存了最优和,没有保存对应最优子集的选中状态。结合你正在用的二进制掩码枚举子集的逻辑,最简单的实现方式是额外存一个整数变量记录最优子集对应的掩码值,最后输出时直接根据这个掩码筛选元素即可,完全不需要用到你没学过的列表和自定义方法。
需要修改的核心点:
- 新增
bestMask变量保存最优子集的二进制掩码,新增bestDiff变量记录当前最优和与π的差值,避免bestsum初始为0在输入全为负数等极端场景下的判断错误 - 每次判断当前子集和更接近π时,除了更新
bestsum,同时把当前的掩码j赋值给bestMask - 最后输出子集时,遍历
bestMask的每一位,输出对应位为1的元素即可
修改后完整代码
import java.util.Scanner; public class ClosestSubsetToPi { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("How many numbers should be read? "); int count = input.nextInt(); double[] data = new double[count]; double bestsum = 0.0; // 保存最优子集对应的二进制掩码 int bestMask = 0; // 初始差值设为最大值,保证第一个子集一定会触发更新 double bestDiff = Double.MAX_VALUE; // 输入逻辑保留你原来的实现 for (int i = 0; i < count; i++) { if ((i + 1) % 10 == 1) { System.out.println("Enter " + (i + 1) + "st number: "); data[i] = input.nextDouble(); } else if ((i + 1) % 10 == 2) { System.out.println("Enter " + (i + 1) + "nd number: "); data[i] = input.nextDouble(); } else if ((i + 1) % 10 == 3) { System.out.println("Enter " + (i + 1) + "rd number: "); data[i] = input.nextDouble(); } else { System.out.println("Enter " + (i + 1) + "th number: "); data[i] = input.nextDouble(); } } for (int j = 0; j < (1 << count); j++) { System.out.print("{ "); double sum = 0.0; for (int x = 0; x < count; x++) { if ((j & (1 << x)) > 0) { System.out.print(data[x] + " "); sum += data[x]; } } System.out.println("}"); double currentDiff = Math.abs(sum - Math.PI); if (currentDiff < bestDiff) { bestDiff = currentDiff; bestsum = sum; // 同步保存当前最优子集的掩码 bestMask = j; } } // 输出结果 System.out.println("最接近π的和值:" + bestsum); System.out.print("对应子集:["); boolean hasPrint = false; for (int x = 0; x < count; x++) { if ((bestMask & (1 << x)) > 0) { if (hasPrint) { System.out.print(", "); } System.out.print(data[x]); hasPrint = true; } } System.out.println("]"); input.close(); } }
小提示:该方案仅适合输入数量小于30的场景,超过30后
1 << count会超出int的取值范围,作为新手练习完全够用。
内容的提问来源于stack exchange,提问作者BBA_Nebula
相关产品推荐
相关产品推荐

