当前位置: 首页 > 知识库问答 >
问题:

如何在分区算法中检索子集?

韦欣德
2023-03-14

我有一个数组,我想把它分成两部分,使它们的总和相等,例如[10, 30, 20, 50]可以分成[10,40],[20,30]。两者的总和都是50。这本质上是划分算法,但我希望检索子集,而不仅仅是识别它是否可划分。所以,我继续做了以下事情:

更新:更新脚本以处理重复项

from collections import Counter

def is_partitionable(a):
    possible_sums = [a[0]]
    corresponding_subsets = [[a[0]]]
    target_value = sum(a)/2
    if a[0] == target_value:
        print("yes",[a[0]],a[1:])
        return
    for x in a[1:]:
        temp_possible_sums = []
        for (ind, t) in enumerate(possible_sums):
            cursum = t + x
            if cursum < target_value:
                corresponding_subsets.append(corresponding_subsets[ind] + [x])
                temp_possible_sums.append(cursum)
            if cursum == target_value:
                one_subset = corresponding_subsets[ind] + [x]
                another_subset = list((Counter(a) - Counter(one_subset)).elements())
                print("yes", one_subset,another_subset)
                return
        possible_sums.extend(temp_possible_sums)
    print("no")
    return

is_partitionable(list(map(int, input().split())))

样本输入

>>> is_partitionable([10,30,20,40])
yes [10, 40] [30, 20]
>>> is_partitionable([10,30,20,20])
yes [10, 30] [20, 20]
>>> is_partitionable([10,30,20,10])
no

我基本上存储了相应的值,这些值是为了在corresponding_subsets中获得值而添加的。但是,随着a大小的增加,很明显corresponding_subsets会有太多的子列表(等于possible_sums中的元素数量)。有没有更好/更有效的方法来做到这一点?

共有2个答案

陶英纵
2023-03-14

这是我实现@sasha的算法的可行性。

def my_part(my_list):
    item = my_list.pop()
    balance = []
    temp = [item, -item]
    while len(my_list) != 0:
        new_player = my_list.pop()
        for i, items in enumerate(temp):
            balance.append(items + new_player)
            balance.append(items - new_player)
        temp = balance[:]
    balance = set(balance)
    if 0 in balance:
        return 'YES'
    else:
        return 'NO'

我也在做回溯。

许寒
2023-03-14

尽管这仍然是一个难题,但您可以尝试以下方法。我假设有n个元素,它们存储在名为arr的数组中(我假设基于1的索引)。让我们组成两个小组AB,这样我想在小组AB之间划分arr的元素,这样两个小组中的元素总和相等。arr的每个元素都有一个选项,可以转到团队A或团队B。假设一个元素(比如第i个元素)进入团队A我们用-A[i]表示它,如果它进入团队B我们就让它成为A[i]。因此,在将每个元素分配给一个团队后,如果总和为0我们的工作就完成了。我们将创建n集(它们不存储重复项)。我将使用示例arr={10,20,30,40}。遵循以下步骤

set_1 = {10,-10} # -10 if it goes to Team A and 10 if goes to B

set_2 = {30,-10,10,-30} # four options as we add -20 and 20

set_3 = {60,0,20,-40,-20,-60} # note we don't need to store duplicates

set_4 = {100,20,40,-40,60,-20,-80,0,-60,-100} # see there is a zero means our task is possible

现在,您所要做的就是从上一组中的0回溯,以查看第i个元素a[i]是否添加为a[i]-a[i],即是否添加到团队aB

编辑

回溯程序。所以我们有n集合,从set_1set_n。让我们制作两个列表list_A来推送属于团队A和类似的list_B的元素。我们从set_n开始,因此使用一个变量current_set最初具有值n。此外,我们还关注最后一个列表中的元素0,因此使用一个变量current_element最初具有值0。遵循下面代码中的方法(我假设所有的集合1到n都已经形成,为了方便起见,我将它们存储为列表列表,但是您应该使用集合数据结构)。下面的代码也假设在最后一个列表中看到了0。我们的任务是可能的。

sets = [ [0], #see this dummy set it is important, this is set_0
              #because initially we add -arr[0] or arr[0] to 0
         [10,-10],
         [30,-10,10,-30],
         [60,0,20,-40,-20,-60],
         [100,20,40,-40,60,-20,-80,0,-60,-100]]

# my array is 1 based so ignore the zero
arr = [0,10,20,30,40]

list_A = []
list_B = []

current_element = 0
current_set = 4 # Total number of sets in this case is n=4

while current_set >= 1:
   print current_set,current_element
   for element in sets[current_set-1]:
     if element + arr[current_set] == current_element:
       list_B.append(arr[current_set])
       current_element = element
       current_set -= 1
       break
     elif element - arr[current_set] == current_element:
       list_A.append(arr[current_set])
       current_element = element
       current_set -= 1
       break


print list_A,list_B
 类似资料:
  • 二分搜索 在计算机科学中,二分搜索(binary search),也称折半搜索(half-interval search)、对数搜索(logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。 搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间

  • 类似Bigtable的数据库存储按其键排序的行。 Cassandra使用分区和聚类键的结合来保持数据的分布和排序;但是,您只能通过使用分区键来选择行! 用于上述查询的Cassandra存储层的可视化。

  • 操作系统实现了各种算法,以便找出链表中的空洞并将它们分配给进程。 关于每种算法的解释如下。 1. 第一拟合算法 第一拟合算法(First Fit)算法扫描链表,每当它找到第一个足够大的孔来存储进程时,它就会停止扫描并将进程加载到该进程中。 该过程产生两个分区。 其中,一个分区将是一个空洞,而另一个分区将存储该进程。 First Fit算法按照起始索引的递增顺序维护链表。这是所有算法中最简单的实现方

  • 假设我正在为评论系统使用Firebase,我想检索给定主题的评论,但是一个主题中有太多评论,我不想一次检索所有评论。我还希望最新的评论显示在顶部。 似乎以相反顺序显示firebase记录的唯一方法是检索所有记录,然后反向迭代它们。 这在大型数据集上可能会变得非常笨拙,尤其是对于移动客户端。 有更好的方法吗?从Firebase按升序或降序查询分页数据的通用和首选解决方案是什么?

  • 我需要一些帮助来了解spark如何决定分区的数量,以及它们在executors中是如何处理的,我很抱歉这个问题,因为我知道这是一个重复的问题,但即使在阅读了许多文章后,我仍然不能理解我正在放上一个我目前正在工作的真实生活用例,以及我的Spark提交配置和集群配置。 我的硬件配置: < code>3节点计算机,总Vcores=30,总内存=320 GB。 我正在使用spark dataframe J

  • 问题内容: 考虑一个非常简单的模型,其中我们有位置,每个位置可以有零个或多个事件。位置将具有名称,描述和地理位置数据(经度/纬度)之类的属性。事件应附加到一个位置(其父级),并应具有名称和描述。 我想要做的是查询子文档(事件),以对其名称和描述进行全文搜索。我想找回匹配的事件,还可以获取其父位置的名称。我还想通过位置坐标缩小结果集。我不想获取与查询不匹配的任何事件。在Elastic Search中