【问题标题】:Can I partition the array in K sizes?我可以将数组划分为 K 个大小吗?
【发布时间】:2016-01-09 04:21:13
【问题描述】:

我正在尝试从这个问题中实现算法:Need idea for solving this algorithm puzzle,但我缺少一些导致我的代码进入无限循环的边缘情况。我可以通过做一些外观改变来解决它,但它表明我不理解算法。

谁能帮帮我,我错过了什么?

#include <stdio.h>

#define max(a, b) (((a)>(b))?(a):(b));
int get_max(int *a, int i, int size)
{
    if (i >= size)
        return 0;
    return max(a[i], get_max(a, i+1, size));
}

int get_sum(int *a, int i, int size)
{
    if (i >= size)
        return 0;
    return a[i] + get_sum(a, i+1, size);
}

int get_partition(int *a, int size, int bound) {
    int running_sum = 0;
    int partitions = 0, i;

    for (i=0;i<size;i++) {
        if (a[i] + running_sum <= bound) {
            running_sum += a[i];
        } else {
            running_sum = 0;
            running_sum += a[i];
            partitions++;
        }
    }
    return partitions;
}

int foo(int *a, int size, int k)
{
    int lower = get_max(a, 0, size);
    int higher = get_sum(a, 0, size);
    int partition;

    while (lower < higher) {
        int bound = (lower + (higher))/2;

        partition = get_partition(a, size, bound);
        printf("partition %d bound %d lower %d higher %d\n", partition, bound, lower, higher);
        if (partition >= k) 
            lower = bound;
        else
            higher = bound;
    }
    return partition;
}

#define SIZE(a) sizeof(a)/sizeof(a[0])
int main(void) {
    int a[] = {2, 3, 4, 5, 6};
    printf("%d\n", foo(a, SIZE(a), 3));
    return 0;
}

输出:

partition 1 bound 13 lower 6 higher 20
partition 2 bound 9 lower 6 higher 13
partition 3 bound 7 lower 6 higher 9
partition 3 bound 8 lower 7 higher 9
partition 3 bound 8 lower 8 higher 9
...last line keeps repeating.

【问题讨论】:

  • 请包括输出的前两行重复行及其前面的一到三行。猜测:lower == bound == Higher-1

标签: algorithm dynamic-programming partitioning greedy


【解决方案1】:

你有几个错误:

  • 在二分搜索期间,您的 while 测试应该是 while (lower+1 &lt; higher) { 而不是 while (lower &lt; higher) {。当lower = 8higher = 9 时,您正在进入无限循环。在这个阶段,您的bound 将是(lower+higher)/2=8,您将更新lower = bound,这不会改变任何内容。
  • foo 的末尾,您应该返回higher(不是分区),因为您的二分搜索不变式是,对于拥有bound &lt;= lower,您可以将数组划分为多个k 部分和bound &gt;= higher 您可以将其分区为k 或更少。
  • 您对get_partition 的计算是错误的。您不考虑最后一个分区组,因为您仅在溢出running_sum 时更新partitions。在 for-cycle 之后,您应该有以下语句:

    if (running_sum > 0) 
        partitions++; 
    

把它们放在一起:

#include <stdio.h>

#define max(a, b) (((a)>(b))?(a):(b));
int get_max(int *a, int i, int size)
{
    if (i >= size)
        return 0;
    return max(a[i], get_max(a, i+1, size));
}

int get_sum(int *a, int i, int size)
{
    if (i >= size)
        return 0;
    return a[i] + get_sum(a, i+1, size);
}

int get_partition(int *a, int size, int bound) {
    int running_sum = 0;
    int partitions = 0, i;

    for (i=0;i<size;i++) {
        if (a[i] + running_sum <= bound) {
            running_sum += a[i];
        } else {
            running_sum = 0;
            running_sum += a[i];
            partitions++;
        }
    }
    if (running_sum > 0)
        partitions++;
    return partitions;
}

int foo(int *a, int size, int k)
{
    int lower = get_max(a, 0, size);
    int higher = get_sum(a, 0, size);
    int partition;

    while (lower+1 < higher) {
        int bound = (lower + (higher))/2;

        partition = get_partition(a, size, bound);
        printf("partition %d bound %d lower %d higher %d\n", partition, bound, lower, higher);
        if (partition > k)
            lower = bound;
        else
            higher = bound;
    }
    printf("partition %dlower %d higher %d\n", partition, lower, higher);
    return higher;
}

#define SIZE(a) sizeof(a)/sizeof(a[0])
int main(void) {
    int a[] = {2, 3, 4, 5, 6};
    printf("%d\n", foo(a, SIZE(a), 3));
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-28
    • 2014-09-20
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多