假设我有一组整数,我想要找出满足特定不等式的所有最大整数数。为了便于说明,
r 1 ,r 2 ,r 3 ,... r n 当r i 是一个正整数。我希望找到最大的z,其范围从1到n,其中r i < = 0.5 *(r 1 + r 2 + r 3 + ... + r n ) all i从3到z。如何解决这些问题?我已经接近了寻找从1到n的所有大小子集的天真方法,并迭代每个子集以检查每个元素是否满足条件?还有其他方法吗?
答案 0 :(得分:0)
我觉得有点不好,特别是对于我对这个问题所做的错误编辑......无论如何:
首先,解决这个问题的最天真,直接和直接的方式;这将是从集合中的第一个数字开始,计算每一步的n
部分和,将该部分和与从第3个元素开始的每个元素的双重进行比较,直到{{1元素。如果每个元素的比较成立,则将当前的最后一个标记为最大n
。
以下宏z
依赖于函数largestzfinder
来执行:
largestzfinderfunc
使用这种方法,我们会从最小的z 开始逐渐到达// indices are zero based
#define largestzfinder(_x_) largestzfinderfunc((_x_), sizeof(_x_) / sizeof(*_x_))
unsigned int largestzfinderfunc( unsigned int set[], size_t size ) {
unsigned int largestz = 0;
unsigned int partialsumsofar = 0;
int disqualified;
for ( int i = 0; i < size; i++ ){
partialsumsofar += set[i];
disqualified = 0;
for ( int j = 2; j <= i; j++ ) { // for all j from 2 to i (inclusive)
if ( 2 * set[j] > partialsumsofar ) {
disqualified = 1;
break;
}
}
if ( !disqualified ) // if comparison held for all j
largestz = i;
}
return largestz;
}
并找到下一个更大的z ,直到我们到达最大。我们可以从最后开始简化该过程,在这种情况下,除了最大之外,我们不必经历所有其他largestz
,我们不会&# 39;不需要其他人......
要做到这一点,我们需要预先计算整个总和,然后逐个减少元素,以相同的方式与缩小的部分和进行比较,并在我们找到时立即返回答案非z
候选人。以下代码执行:
disqualified
现在,您看,我们检查条件是否适用于从第3个到最后一个的每个元素,一个接一个...而我们可以检查它们中最大的元素!如果// indices are zero based
#define largestzfinder(_x_) largestzfinderfunc((_x_), sizeof(_x_) / sizeof(*_x_))
unsigned int largestzfinderfunc( unsigned int set[], size_t size ) {
unsigned int largestz = 0;
unsigned int partialsumsofar = 0;
int disqualified;
for ( int i = 0; i < size; i++ )
partialsumsofar += set[i];
for ( int i = size - 1; i >= 0; i-- ){
disqualified = 0;
for ( int j = 2; j <= i; j++ ) { // for all j from 2 to i (inclusive)
if ( 2 * set[j] > partialsumsofar ) {
disqualified = 1;
break;
}
}
if ( !disqualified ) { // if comparison held for all j
largestz = i;
break;
}
partialsumsofar -= set[i]; // updates/reduces partialsumsofar
}
return largestz;
}
,则所有这些都只是小于或等于远处的部分和。
您如何确定largestamongthem <= partialsumsofar / 2
?好吧,事情变得复杂,特别是当你从最后开始做这个过程时。如果我们从一开始就这样做,那么我们就可以从largestsofar
开始,并将每个后续元素与它进行比较,更新我们的largestsofar = 0;
。
这样做的一种方法是创建一个与set数组具有相同大小的新整数数组,它将为每个点保存largestsofar
。以下代码使用该方法:
largestsofar
好吧,如果你对分配内存感到非常满意,保留到目前为止最大数量的列表,我就和你在一起。以下递归函数可以完成该操作,而无需保留列表。它看起来也短得多。缺点是它对读者不太友好。这里:
// indices are zero based
#define largestzfinder(_x_) largestzfinderfunc((_x_), sizeof(_x_) / sizeof(*_x_))
unsigned int largestzfinderfunc( unsigned int set[], size_t size ) {
unsigned int largestz = 0;
unsigned int partialsumsofar = 0;
unsigned int * largestsofar = calloc( size, sizeof * largestsofar );
for ( int i = 0; i < size; i++ )
partialsumsofar += set[i];
largestsofar[0] = 0;
largestsofar[1] = 0;
largestsofar[2] = set[2];
for ( int i = 3; i < size; i++ )
largestsofar[i] = (set[i] > largestsofar[i-1]) ? set[i] : largestsofar[i-1];
for ( int i = size - 1; i >= 0; i-- ){
if ( 2 * largestsofar[i] <= partialsumsofar ) {
largestz = i;
break;
}
partialsumsofar -= set[i];
}
free( largestsofar );
return largestz;
}
让我简要解释它的作用:通过调用宏,它首先将// indices are zero based
#define largestzfinder(_x_) largestzfinderfunc((_x_), sizeof(_x_) / sizeof(*_x_), (_x_)[0] + (_x_)[1], 1, 0)
unsigned int largestzfinderfunc( unsigned int set[], size_t size, unsigned int partialsumsofar, unsigned int i, unsigned int largestsofar ){
unsigned int j;
if ( i < size - 1 && ( j = largestzfinderfunc( set, size, partialsumsofar + set[i + 1], i + 1, ( set[i + 1] > largestsofar ) ? set[i + 1] : largestsofar ) ) ){
return j;
}
else if ( 2 * largestsofar <= partialsumsofar ) {
return i;
}
else
return 0;
}
作为r_0 + r_1
传递,partialsumsofar
作为要检查的当前z,并{{1 }}作为1
之前的最大数字(这是因为在比较期间不会考虑0
和r_1
。
r_0
),它将调用超出一级的函数,更新r_1
,增加当前z的增量,以及更新的最大数字。这将完成,直到到达最后一个元素。
之后,递归树将崩溃。如果最后一个不满足条件,它将返回i < size - 1
,导致父递归分支检查他/她是否满足条件。
只要一个父级满足条件,它就会返回当前的z,导致每个父级返回相同的z,因为它们都将返回的值存储在partialsumsofar
下并返回它,如果{{1}不是零。
本质上,它实际上为每个0
和j
以及所有这些都分配了内存,但它将所有这些一个一个地释放为递归树/行/任何崩溃。
这不是简短,但无论如何,我希望我这次做得对。我现在想解决这个问题......