解题思路: 递归,深搜

这个真的 最后的再非3和非5的列表中 查找多数之和是否存在和为target的可能。看了题解,睡前灵光一现 才想通。期间考虑过01背包思想。

  • 此题最主要解决的问题是 求列表中 是否存在多数之和 = target目标题。
  • 底层思维为: 假设 当前数是 target的一个加数, 另一个是假设 不是一个加数。 一次在递归的时候,每次的下标后移,都会对应两种可能的目标值: target (当前数不当做加数,计算下一个数), 或者 target-当前数 (将当前数作为一个加数,找剩余的list数据中 是否存在 新的目标和)。 下一轮递归的结果 依旧会对应上述说的俩种情况, 也就能够实现 以下这种情景:
  • 如target =10, list = 2,5,4,3; 明显2+5+3=10;但是中间多了个4.
  • 也就是 当i走到3时,下标后移时, 可以加4 求新目标值; 也会走 不加四,当时目标和不变 下标+1。
import java.util.*;

import java.util.stream.Collectors;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int n = in.nextInt();
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < n; i++) {
                list.add(in.nextInt());
            }

            // 给定几个数组,5的倍数必须在一个数组,3的倍数必须在另一个数组,  其他的随意
            List<Integer> five = new ArrayList<>();
            List<Integer> three = new ArrayList<>();
            List<Integer> other = new ArrayList<>();

            for (int i = 0; i < list.size(); i++) {
                int value = list.get(i);
                if (value % 3 == 0) {
                    three.add(value);
                } else  if (value % 5 != 0) {
                    other.add(value);
                }
            }

            int threeSum = three.stream().mapToInt(Integer::intValue).sum();
            int sum = list.stream().mapToInt(Integer::intValue).sum();

            // 根据题意可以得出,在other列表中存在一个数字或者多个数字的和 为一下公式的值。
            // s5 + m = s3 + n;
            // (s5 + m) + (s3 + n) = sum;
            // 可以推出: n = sum/2 - s3;
            int t = sum / 2 - threeSum;

            if (sum % 2 != 0) {
                System.out.println(false);
            } else {
                //否则,在剩余数中找目标数字
                System.out.println(helper(other, t, 0));
            }
        }
    }

    private static boolean helper(List<Integer> list, int target, int start) {
        if (start == list.size()) return target == 0;//终止条件

        // 针对每一个数组,都有 求和=target   使用它和不使用它的情况 计算。    使用 即target不变,不实用则target-start的值。
        // 类似于01背包的思想
        return helper(list, target - list.get(start), start + 1) ||
               helper(list, target, start + 1);
    }



}