java - 一组子集中的数字总和

标签 java optimization powerset

我有一个集合 S 像这样 [00 01 10 11] 和一个元素 E 作为 11 .我想找出这个集合中有多少个子集的位数之和大于或等于元素 E 的位数之和。

例如,在这种情况下,答案是 10。 满足约束的10组是:

00 01 10 11 // Sum is 3 which is greater than 2 (sum of digits of E)
00 01 11 
00 10 11
01 10 11
00 11
01 11
10 11
11
00 01 10
01 10

上述子集的所有位数之和大于等于2(E的位数之和)。

我尝试了以下

public static void main(String[] args) {
    Set<String> inputSet = new HashSet<String>();
    Scanner sc = new Scanner(System.in);
    int N = sc.nextInt();
    int M = sc.nextInt();// specifies the length of the digts in the set.
    for (long i = 0 ; i < N; i++) {
        inputSet.add(sc.next());
    }
    long sum = 0;
    String E = sc.next();//
    sc.close();
    for (String str : E.split("(?!^)")) {
        sum = sum + Integer.parseInt(str);
    }
    List<Set<String>> subSets = new ArrayList<Set<String>>();
    for (String addToSets : inputSet) {
        List<Set<String>> newSets = new ArrayList<Set<String>>();
        for (Set<String> curSet : subSets) {
            Set<String> copyPlusNew = new HashSet<String>();
            copyPlusNew.addAll(curSet);
            copyPlusNew.add(addToSets);
            newSets.add(copyPlusNew);
        }
        Set<String> newValSet = new HashSet<String>();
        newValSet.add(addToSets);
        newSets.add(newValSet);
        subSets.addAll(newSets);
    }
    long sum1;
    long count = 0;
    for (Set<String> set : subSets) {
        sum1 = 0;
        for (String setEntry : set) {
            for (String s : setEntry.split("(?!^)")){
                sum1 = sum1 + Integer.parseInt(s);
            }
        }
        if (sum == sum1 || sum1 > sum)
            count = count+1;
    }
    System.out.println(count);
}

约束条件 1 <= N <= 10^5


1 <= 米 <= 20

上述方法不适用于 105 范围内的集合大小。请帮助为此提供一种有效的方法。 谢谢!

最佳答案

解决这个问题的关键在于记住加法是结合的。所以当你添加这些数字并不重要。因此,如果我们将其简化为已知问题,则很容易解决。

将您的输入数组转换为数字总和。也就是说,如果您的原始数组是 A,那么与结果数组 B 的关系将是:

          B[i] = sum of digits of(A[i]).

假设 K 是数字总和(E)

然后你的问题减少到

     Find number of subsets in B whose sum is <= K

这很容易。

编辑:

  public static void main(String[] args) {
    int[] A ={01,11,111};
    int B[] = new int[A.length];
    for(int i=0;i<A.length;i++){
        B[i]=getDigitSum(A[i]);
    }
     int E = 11;
    int K= getDigitSum(E);
    int N =B.length;
    Arrays.sort(B);
    int DP[][] = new int[B.length][B[B.length-1]+1];


    for (int i=0;i<N;i++) {
        DP[i][B[i]] = 1;

        if (i == 0) continue;

        for (int k=0;k<K;k++) {
            DP[i][k] += DP[i - 1][k];
        }
        for (int k=0;k<K;k++) {
            if( k + B[i] >= K) break ;
            DP[i][k + B[i]] += DP[i - 1][k];
        }
    }
    int sum=0;
    for(int i=0;i<K;i++) {
        sum = sum +DP[N-1][i];
    }
    int result = ((int)Math.pow(2,N)) - sum-1;
    System.out.println(result);

}

private static int getDigitSum(int num) {
    int sum =0;
    while(num >0){
       sum=sum+ (num%10);
        num= num/10;
    }
    return sum;
}

关于java - 一组子集中的数字总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31325982/

相关文章:

java - 如何通过在 android 中启动一个新的 Activity 来处理 IOException

python - Python中Powerset的时间复杂度

c++ - 写入文件时出现堆损坏

java - Spring 网络服务 : easy way to un-marshall a bean to XML client side?

java - 远程 JNDI 查找返回我自己的 EJB

python - 将一个巨大的数字乘以 random() (Python)

ios - Accelerate Framework 能否基于单独的索引数组聚合数组值?

python - 有什么办法可以把它变成列表理解

f# - 懒惰地生成powerset

java - 是否可以让用户编辑 R.string?