优化并找到这种不等式的计算

时间:2014-03-22 16:13:25

标签: java c algorithm

假设我有一组整数,我想要找出满足特定不等式的所有最大整数数。为了便于说明,

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的所有大小子集的天真方法,并迭代每个子集以检查每个元素是否满足条件?还有其他方法吗?

1 个答案:

答案 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之前的最大数字(这是因为在比较期间不会考虑0r_1

但是,它并没有立即检查;如果这不是最后一个元素(r_0),它将调用超出一级的函数,更新r_1,增加当前z的增量,以及更新的最大数字。这将完成,直到到达最后一个元素。

之后,递归树将崩溃。如果最后一个不满足条件,它将返回i < size - 1,导致父递归分支检查他/她是否满足条件。

只要一个父级满足条件,它就会返回当前的z,导致每个父级返回相同的z,因为它们都将返回的值存储在partialsumsofar下并返回它,如果{{1}不是零。

本质上,它实际上为每个0j以及所有这些都分配了内存,但它将所有这些一个一个地释放为递归树/行/任何崩溃。

这不是简短,但无论如何,我希望我这次做得对。我现在想解决这个问题......