首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >统计和大于等于k的子集个数

统计和大于等于k的子集个数
EN

Stack Overflow用户
提问于 2017-07-26 13:07:06
回答 2查看 3.6K关注 0票数 1

给定一个有n个元素的数组,需要计算和大于或等于k的子集的数量。

例如arr[] = {1,5,9,2,3},k =16

1+5+9+2=17

1+5+9+3=18

1+5+9+2+3=20

5+9+2=16

5+9+3=17

5+9+2+3=19

答案是6。

我所知道的一种方法是使用位掩码的动态编程,并检查是否为sum>=k,并递增计数。这种方法的问题是N应该非常小,因为位掩码涉及指数运行时间。

对于上述问题,有没有其他有效的算法?

提前谢谢。

EN

回答 2

Stack Overflow用户

发布于 2017-07-26 14:27:52

生成Counts[Sum+1]数组,其中Sum是所有元素的总和

设置Counts[0] = 1,其他元素-零

For ever x=arr[i] scan Counts数组从末尾开始并递增这些条目,这些条目可以由目前为止的sums和x组成

代码语言:javascript
复制
if Counts[j - arr[i]] > 0 then  //this check might be omitted
   Counts[j] = Counts[j - arr[i]] +  Counts[j]

然后对j>=k的非零计数项求和

复杂性是O(Sum * N)

如果可能的和的范围很大,但可能的和的数量不是很大(如arr=[1, 2, 3, 100000000, 100000001]数组),您可以利用记忆化方法,只在映射中存储真正存在的变体

示例:

代码语言:javascript
复制
arr=[1,2,3,5]
Counts = [1,0,0,0,0,0,0,0,0,0,0,0]
after arr[0]=1
Counts = [1,1,0,0,0,0,0,0,0,0,0,0]
after arr[1]=2
Counts = [1,1,1,1,0,0,0,0,0,0,0,0]
after arr[2]=3
Counts = [1,1,1,2,1,1,1,0,0,0,0,0]
after arr[3]=5
Counts = [1,1,1,2,1,2,2,1,2,1,1,1]

Counts[8] could be composed from 5 and existing Counts[3] with two variants
1+2+5; 3+5
票数 1
EN

Stack Overflow用户

发布于 2017-07-26 15:39:01

一种方法是使用递归创建子集,并在原始集合中省略的元素的总和大于total-k时停止递归,其中total是数组中所有元素的总和。

下面是一些说明该方法的Java代码:

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

public class SubSet
{

    public static void main(String[] args)
    {
        Integer[] set = { 1, 5, 9, 2, 3 };
        List<List<Integer>> subsets = subsetsK(set, 16);
        for (List<Integer> subset : subsets)
        {
            System.out.println(subset);
        }
    }

    static List<List<Integer>> subsetsK(Integer[] arr, int k)
    {
        int t = 0;
        for (int n : arr) t += n;

        List<List<Integer>> subsets = new ArrayList<>();
        allSubsets(subsets, arr, new BitSet(arr.length), 0, 0, t - k);
        return subsets;
    }

    public static void allSubsets(List<List<Integer>> subsets, Integer[] arr, BitSet off, int pos, int sum, int lim)
    {
        if(sum > lim) return;

        if(pos == arr.length)
        {
            subsets.add(toSubset(arr, off));
            return;
        }

        off.set(pos);
        allSubsets(subsets, arr, off, pos + 1, sum + arr[pos], lim);

        off.clear(pos);
        allSubsets(subsets, arr, off, pos + 1, sum, lim);
    }

    static List<Integer> toSubset(Integer[] arr, BitSet off)
    {
        List<Integer> ss = new ArrayList<>();
        for (int i = 0; i < arr.length; i++)
        {
            if (!off.get(i))
                ss.add(arr[i]);
        }
        return ss;
    }   
}

输出:

代码语言:javascript
复制
[5, 9, 3]
[5, 9, 2]
[5, 9, 2, 3]
[1, 5, 9, 3]
[1, 5, 9, 2]
[1, 5, 9, 2, 3]

您可以在此处运行/编辑代码:Ideone

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45317897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档