Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 无排序的顶K子集和_Arrays_Algorithm_Subset - Fatal编程技术网

Arrays 无排序的顶K子集和

Arrays 无排序的顶K子集和,arrays,algorithm,subset,Arrays,Algorithm,Subset,给定一个大小为N的数组,打印大小为K的所有子集(0我将这样解决此问题: for each count of elements to use for each possible sum for each starting index count of ways to get there (with or without that starting index) counts_by_count_by_sum_by_index = [ { #

给定一个大小为N的数组,打印大小为K的所有子集
(0我将这样解决此问题:

for each count of elements to use
    for each possible sum
        for each starting index
            count of ways to get there (with or without that starting index)
counts_by_count_by_sum_by_index = [
    { # empty sets
        0: [1, 1, 1, 1]
    },
    { # 1 element sets
        3: [1, 1, 1, 0],
        6: [1, 0, 0, 0],
        8: [1, 1, 0, 0],
        9: [1, 1, 1, 1],
    },
    { # 2 element sets
        9: [1, 0, 0, 0],
       11: [1, 1, 0, 0],
       12: [1, 1, 1, 0],
       14: [1, 0, 0, 0],
       15: [1, 0, 0, 0],
       17: [1, 1, 0, 0],
    },
    { # 3 element sets
       17: [1, 0, 0, 0],
       18: [1, 0, 0, 0],
       20: [1, 1, 0, 0],
       23: [1, 0, 0, 0],
    },
    { # 4 element sets
       26: [1, 0, 0, 0]
    }
]
  • 对数组进行排序,让
    s
    为前
    k
    个元素的总和
  • 使用函数生成等于
    s
    的所有总和子集
  • 找到最小的
    s2>s
    ,这样就有了一个子集,其总和等于
    s2
    ,使用
  • 如果存在此类
    s2
    ,则设置
    s=s2
    并转至步骤2。否则,停止
  • 这里是Python中的一个实现:它按照和的顺序惰性地生成每个子集,因此您可以只获取它生成的第一个T子集

    def子集的求和顺序(lst,k):
    """
    返回生成k元素子集的生成器
    对于lst,按其和的递增顺序。
    """
    lst=已排序(lst)
    s=总和(lst[:k])
    max_s=总和(lst[-k:]
    虽然s不是无:
    _和(lst,k,s)的子集_的收益率
    s=范围内的最小和(lst、k、s+1、最大)
    def_和的子集(lst,k,s,t=(),i=0):
    """
    返回生成元组t+tt的生成器,其中tt
    是lst[i:]的k元素子集,其和为s
    子集是按字典顺序产生的
    必须对lst进行排序。
    """
    如果k<0:
    提升值错误()
    elif k==0:
    如果s==0:
    产量t
    其他:
    对于范围(i,len(lst)-k+1内的j:
    如果和(lst[j:j+k])>s:break
    v=lst[j]
    s2=s-v
    t2=t+(v,)
    _和(lst,k-1,s2,t2,j+1)的子集_的收益率
    定义范围内的最小和(lst、k、min、max、i=0):
    """
    
    返回最小的s,使min_s一种方法涉及动态规划

    首先,想象一下,如果我们有一个如下所示的数据结构:

    for each count of elements to use
        for each possible sum
            for each starting index
                count of ways to get there (with or without that starting index)
    
    counts_by_count_by_sum_by_index = [
        { # empty sets
            0: [1, 1, 1, 1]
        },
        { # 1 element sets
            3: [1, 1, 1, 0],
            6: [1, 0, 0, 0],
            8: [1, 1, 0, 0],
            9: [1, 1, 1, 1],
        },
        { # 2 element sets
            9: [1, 0, 0, 0],
           11: [1, 1, 0, 0],
           12: [1, 1, 1, 0],
           14: [1, 0, 0, 0],
           15: [1, 0, 0, 0],
           17: [1, 1, 0, 0],
        },
        { # 3 element sets
           17: [1, 0, 0, 0],
           18: [1, 0, 0, 0],
           20: [1, 1, 0, 0],
           23: [1, 0, 0, 0],
        },
        { # 4 element sets
           26: [1, 0, 0, 0]
        }
    ]
    
    编写代码来填写此信息并不难。对于
    [6,8,3,9]
    您将得到如下结果:

    for each count of elements to use
        for each possible sum
            for each starting index
                count of ways to get there (with or without that starting index)
    
    counts_by_count_by_sum_by_index = [
        { # empty sets
            0: [1, 1, 1, 1]
        },
        { # 1 element sets
            3: [1, 1, 1, 0],
            6: [1, 0, 0, 0],
            8: [1, 1, 0, 0],
            9: [1, 1, 1, 1],
        },
        { # 2 element sets
            9: [1, 0, 0, 0],
           11: [1, 1, 0, 0],
           12: [1, 1, 1, 0],
           14: [1, 0, 0, 0],
           15: [1, 0, 0, 0],
           17: [1, 1, 0, 0],
        },
        { # 3 element sets
           17: [1, 0, 0, 0],
           18: [1, 0, 0, 0],
           20: [1, 1, 0, 0],
           23: [1, 0, 0, 0],
        },
        { # 4 element sets
           26: [1, 0, 0, 0]
        }
    ]
    
    如果您有更多的元素,此数据结构可以以伪多项式的方式变大,但可以扩展。具体来说,
    O((元素大小)*(集合大小)^3)

    使用这种数据结构,很容易编写按和搜索,然后按字典顺序(按使用的索引)递归查找解决方案


    如果你愿意,你也可以找到,比如说,第一百万个解是什么,而不必生成之前的解。

    只是一个想法。如果
    K
    是3,你取输入数组中最小的4个元素,你可以从这4个元素中选择3个,得到4个最小的子集。取5个元素,你可以形成最小的5C3子集。@无法使用的用户3386109,例如
    [3,6,7,8,9]
    -您的算法将在
    3,6,9
    之前生成
    6,7,8
    。我不确定我错过了哪一步。我想说的是,对于某些输入,可能有一个子集包含数组的最后一个元素,它比不包含数组的第一个元素的任何子集都小,因此任何基于yieldin的算法数组前缀不断增加的g子集是行不通的。你说的“取输入数组中最小的4个元素,通过选择其中的3个,你将得到4个最小的子集”是错误的。我要强调的是,对于某些输入,可能有一个子集包含数组的最后一个元素"我假设你的意思是,对于某些输入,可以有一个子集包含数组中最大的元素。对吗@kaya3@kaya3好的,我最初的想法是,在一般情况下,不需要数组中的最大元素。例如,如果
    k=3
    T=10
    N=100
    ,则不需要数组的第100个元素。需要考虑的是,“你需要数组的多少个元素?”这是一个很好的解决方案,但提前生成所有可能的和相当于在最坏的情况下生成所有(n选择k)组合,不是吗?可以用“准时”编写此算法使用优先级队列实现数据结构。这听起来很有趣。但我必须花很多时间思考如何使其工作。我肯定遗漏了一些东西。这似乎效率极低。对于1000个元素的数组,这将如何工作,并且您需要找到长度为100的前100万个子集,以及最小的总和。对于e例如,你对每一个可能的总和都有
    ,这意味着所有的总和都已生成。我们不是要避免这种情况吗?我非常清楚@btilly的强大,我真的相信我在这里缺少一些东西。@JosephWood我认为
    t=1000000
    不适合这个(不是很小)约束。@JosephWood在我说的优先级队列评论中,但我必须对如何使其工作进行大量思考。这意味着我对如何执行它有很好的想法,但实际实现是复杂的。如果您想尝试一下,您需要用返回的流替换
    k元素集
    s对
    (值,计数)
    。该流应该使用生成的值(如果存在),如果不存在则生成更多。生成更多应该是从优先级队列中选取部分计算。