给定一个大小为 N 的数组,我需要找到在最小和最大范围内求和的最小值数
Posted
技术标签:
【中文标题】给定一个大小为 N 的数组,我需要找到在最小和最大范围内求和的最小值数【英文标题】:Given an array of size N I need to find the min number of values that will sum up within a min and max range 【发布时间】:2011-12-09 18:20:17 【问题描述】:。
例如:考虑一个数组[1,2,3,4,5]。我需要从该数组中找到总和大于 5 且小于 8 的最小值。 Ans:因为 1+5 大于 5 且小于 8,所以值的最小数量是 2 因此答案。
下面是我实现逻辑的函数。
int void CheckValue()
for (i = 0; i <5; i++)
if (a[i] > min && a[i] < max)
return 1;
for (i = 0; i< 4; i++)
for (j = i + 1; j < 5; j++)
if (a[i] + a[j] > min && a[i] + a[j] < max)
return 2;
for (i = 0; i < 3; i++)
for (j = i + 1; j < 4; j++)
for (k = j+1; k < 5; k++)
if (a[i] + a[j] + a[k] > min && a[i] + a[j] + a[k] < max)
return 3;
for (i = 0; i < 2; i++)
for (j = i + 1; j< 3; j++)
for (k = j + 1; k< 4; k++)
for (l = k + 1; l < 5; l++)
if (a[i] + a[j] + a[k] + a[l] > min && a[i] + a[j] + a[k] + a[l] < max)
return 4;
if(a[0]+a[1]+a[2]+a[3]+a[4]>min && a[0]+a[1]+a[2]+a[3]+a[4]<max)
return 5;
return 0;
它工作正常,但问题在于它的复杂性。任何人都可以提供任何建议以进一步优化此代码或提供更好的逻辑来实现它。
【问题讨论】:
数组是否允许包含负数? 如果我在数组中添加第六个元素会怎样? 没有负数只有正数.. @blender 这只是一个展示我如何解决这个问题的例子。数组可以有任意数量的元素,代码会相应地改变...... 数组总是像上面的例子那样排序吗? 【参考方案1】:我会提出以下解决方案:
假设范围的最小值是 minVal,最大值是 maxVal。 现在对数组进行排序。假设数组的长度是 len 对数组中的数字进行二进制搜索,这只是
搜索通行证: 我的意思是如果数字在索引 i 处,那么索引 i+1 处的数字应该 >=maxVal。假设这个数字的索引是 currIndex。 如果此数字等于 maxVal,则在 0 到 currIndex 之间进行二进制搜索以查找数字
minVal 和
搜索失败: 这意味着最高数字是数组小于 maxVal。因此,对于这种情况,请按照以下步骤操作: 1)将数组中的最大数添加到结果集中。 2) 现在从 len-1 t0 1 开始循环。如果 arr[len-1] + arr[len] 小于 maxVal,则将 arr[len-1] 添加到结果集并继续循环。如果 arr[len-1] + arr[len] > maxVal 然后跳过并检查 arr[len-1] + arr[len]。
等等。
【讨论】:
【参考方案2】:我对这类事情没有任何经验,因此可能有更好的方法来做这件事,但我确实有一些可能会有所帮助的见解。
目前您正在计算每个可能的组合,您应该能够更改您的算法以实现它,以便您可以消除一些组合而无需计算它们。
我会先对数组进行排序,这样您就可以在不计算的情况下消除一些值。
例如,如果您有一个看起来像 [1,2,4,5,9] 的数组,并且 min=11 和 max=14,那么您的算法将检查 1+2,1+4,1+5, 1+9 然后 2+4, 2+5, 2+9, 4+5, 4+9 才得出答案。
如果您先从最大的数字开始,您可以通过计算 9+1 来消除所有可能的 1 组合,因为 9+1
【讨论】:
我没有你所写的代码,但它肯定不是一个非常干净的解决方案。【参考方案3】:这是一道作业题吗?
你的问题真的不清楚,但这是我想要的:
排序。 nlogn。 从添加第一个元素和最后一个元素开始。是在范围内吗? 从一端取第一个指针,假设从头开始,将其移动到中间并添加中间数字和最后一个数字,第一个指针+最后一个指针。 是在范围内吗?您可以将第一个指针移动到第一个和最后一个指针之间的中间,即:向右移动序列的 3/4。
所以你在这里使用二分搜索,两个指针在一个排序的序列上。
这将为您提供一个估计的元素数量,这将在范围内。我希望你明白了。
如果总和超出范围,您可以将第二个指针移到中间。
这会给你nlogn。
请注意,这仅适用于两个数字,我不确定您是在询问所有可能的数字,其加法在范围内还是只有两个数字?
两个数字很容易,nlogn做到了
所有可能的子集都是np hard的子集和问题。 2**n 的指数。
【讨论】:
你误解了这个问题。我不想要范围内的元素数。我想要我的问题中明确说明的范围内的最小元素数 你所说的最少元素数到底是什么意思? 如果数组的任何单个元素在范围 den min 元素数为 1 否则如果任何 2 个数组的总和在范围 den min 元素数为 2 else if数组的任意 3 个元素的总和在范围 den 3 之间,依此类推..【参考方案4】:我认为你应该考虑对数组进行排序,有很多有效的算法。
然后从最大值开始,依次累加较小的值,每一步检查条件。
【讨论】:
【参考方案5】:这是一个相当复杂的问题,可能是 np hard。
想到的一件事是它有点类似于“背包问题”。也许您可以找到一个实现并对其进行调整。
如果预计最少的项目数量很少,您当然可以使用蛮力方法:
-
设置 minVal = 1
查找所有大小 minVal 的集合
只要没有一组符合您的条件,就将 minVal 加 1 并转到第 2 步
【讨论】:
以上是关于给定一个大小为 N 的数组,我需要找到在最小和最大范围内求和的最小值数的主要内容,如果未能解决你的问题,请参考以下文章
需要帮助编写一个函数来查找 N 维数组 C++ 中的最大值和最小值