给定一组正整数,其元素不必不同,我需要找到从给定集合的任何子集都不能得到的最小非负和。
例如:如果S={1,1,3,7}
,我们可以得到0
作为(S={})
,1
作为(S={1})
,2
作为(S={1,1})
,3
,4
作为(S“={1,3})
,5
作为(S“={1,1,3})
,但我们无法得到6
。
现在我们得到一个数组A,由N个正整数组成。它们是M个查询,每个查询由两个整数组成,分别描述i't查询:我们需要找到无法从数组元素{A[Li],A[Li 1],…,A[Ri-1],A[Ri]}中获得的和。
我知道用蛮力方法找到它要在O(2^n)中完成。但是给定1≤N,M≤100,000
。这是做不到的。他们的任何有效方法也是如此。
这是子集和问题的一种变体,它是NP完全的,但这里可以采用基于递归公式的伪多项式动态规划解决方案:
f(S,i) = f(S-arr[i],i-1) OR f(S,i-1)
f(-n,i) = false
f(_,-n) = false
f(0,i) = true
递归公式基本上是一个详尽的搜索,如果您可以使用元素i
或在没有元素i
的情况下获得它,则可以实现每个求和。
动态规划是通过构建一个SUM 1 x n 1表(其中SUM是所有元素的总和,n是元素的数量)并自下而上构建来实现的。
像这样的东西:
table <- SUM+1 x n+1 table
//init:
for each i from 0 to SUM+1:
table[0][i] = true
for each j from 1 to n:
table[j][0] = false
//fill the table:
for each i from 1 to SUM+1:
for each j from 1 to n+1:
if i < arr[j]:
table[i][j] = table[i][j-1]
else:
table[i][j] = table[i-arr[j]][j-1] OR table[i][j-1]
一旦你有了表,你需要最小的i
,这样对于所有j
:table[i][j]=false
解决方案的复杂性为O(n*SUM),其中SUM是所有元素的总和,但请注意,在找到所需的数字后,实际上可以修剪算法,而无需继续下一行,这是解决方案不需要的。
假设我们有一个bool
数组,表示迄今为止尚未找到的数字(通过求和的方式)。
对于我们在S的有序(递增值)子集中遇到的每个数字,我们执行以下操作:
使用这种筛选,我们会将所有找到的数字标记为True,当算法完成时,遍历数组会找到最小的不可求和。
显然,我们不能有这样的解决方案,因为数组必须是无限的,才能处理所有的数集。
这个概念可以通过做一些观察来改进。输入1,1,3
,数组变成(按顺序):
可以提出一个重要的意见:
对于7的下一个输入,我们可以断言:
7
7
的数字,则无法获得6
我们可以得出以下结论:
由于(3)和(6),我们实际上不需要数字数组,我们只需要一个值,即max来表示迄今为止找到的最大数字。
这样,如果下一个数字n
大于max 1
,则会产生一个间隙,而max 1
是最小的无法获得的数字。
否则,max
变为max n
。如果我们遍历了整个代码,结果是最大值1。
实际代码(C#,易于转换为C):
static int Calculate(int[] S)
{
int max = 0;
for (int i = 0; i < S.Length; i++)
{
if (S[i] <= max + 1)
max = max + S[i];
else
return max + 1;
}
return max + 1;
}
应该运行得很快,因为它显然是线性时间(O(n))。由于应该对函数的输入进行排序,使用快速排序时,这将变为O(nlogn)。我在不到5分钟的时间内,在8个内核上获得了结果,M=N=100000。
如果数字上限为10^9,则可以使用基数排序来近似O(n)时间进行排序,但是由于需要大量的排序,这仍然会超过2秒。
但是,我们可以在排序之前使用随机1的统计概率来消除子集。开始时,检查S中是否存在1,如果不存在,则每个查询的结果都是1,因为无法获取。
从统计学上讲,如果我们从10^9个数字中随机抽取10^5次,我们有99.9%的几率得不到一个1。
在每次排序之前,检查该子集是否包含1,如果不包含1,则其结果为1。
通过此修改,代码在我的机器上运行只需2毫秒。这是http://pastebin.com/rF6VddTx上的代码
我有一个名为product的MongoDB集合,其中包含以下文档,如下所示。 我想查询收款情况,只退回价格最低的单据,例如: 但当我运行聚合查询时: 它只返回一个文档。
问题内容: 我有ID为的商品。现在我有如下数据。每行都有一个offerId。由数组中的组合组成。是那个的价值 现在,我必须选择所有给我提供最佳ID组合(即最大总折扣)的offerId。 例如,在上述情况下:可能的结果可能是: [o2,o4,o5]最大折扣为。 注意。结果offerId应该不会重复ID。id的示例为[1,3,4],[5],[6]都是不同的。 其他组合可以是: 其id为[1],[3,5
我正在写一个方法,它接受用户的整数输入,并显示总数、平均值、最大值和最小值。 我有总数和平均工作,但我得到2147483647最大和-2147483648最小。 循环只能在用户输入-1时结束。 我的代码:
问题内容: 从对象开始时:将小时作为表现的最佳方法是什么? 我必须迭代几百万个日期,因此性能很重要。 通常情况下,我会得到以下小时,但是也许有更好的方法? 问题答案: 在UTC中: 要么
无法从外壳中删除集合, 集合可用并且我的 php 脚本正在访问它的东西(选择|更新) 但当我使用: 它给了我一个错误:
我正在尝试获取mongodb中存在的所有数据库的值,迭代所有数据库和集合,然后打印it文档。我可以打印作为变量传递集合的文档,但不能在所有数据库和集合上进行迭代(作为变量的值)。有人知道pymongo是否支持动态地作为值传递,而不是将集合和数据库作为变量本身传递?