【问题标题】:How to divide an array of n length into k sub arrays that have approximately equal sizes (in C)?如何将长度为 n 的数组划分为大小大致相等的 k 个子数组(在 C 中)?
【发布时间】:2017-04-04 03:40:17
【问题描述】:

我有一个大小为 n 的数组,想分成 k 个子数组,每个数组的大小必须大致相同。我一直在想,知道你必须使用两个 for 循环,但我很难实现这些 for 循环。

我的尝试:

//Lets call the original integer array with size n: arr
// n is the size of arr
// k is the number of subarrays wanted

int size_of_subArray = n/k;
int left_over = n%k; // When n is not divisible by k
int list_of_subArrays[k][size_of_subArray + 1];

//Lets call the original integer array with size n: arr

for(int i = 0; i < k; i++){
   for(int j = 0; j < size_of_subArray; j++){
       list_of_subArrays[i][j] = arr[j];
   }
}

我正在努力在 forloops 中获取正确的索引。

有什么想法吗?

【问题讨论】:

  • 我已经编辑了我的帖子。
  • @Mat 什么是“n”什么是“k”什么是“arr”?
  • n 是原始数组的大小(称为 arr),k 是想要的子数组的数量。

标签: c arrays sub-array


【解决方案1】:

我已经重构了您的代码并对其进行了注释。

主要有以下几点:

  1. 计算子数组大小时,必须向上取整
  2. arr 的索引需要从 0 继续递增(即它重置为 0)

以下应该可以,但我没有测试它[请原谅无偿的风格清理]:

// Lets call the original integer array with size n: arr
//  n is the size of arr
//  k is the number of subarrays wanted

// round up the size of the subarray
int subsize = (n + (k - 1)) / k;

int list_of_subArrays[k][subsize];

int arridx = 0;
int subno = 0;

// process all elements in original array
while (1) {
    // get number of remaining elements to process in arr
    int remain = n - arridx;

    // stop when done
    if (remain <= 0)
        break;

    // clip remaining count to amount per sub-array
    if (remain > subsize)
        remain = subsize;

    // fill next sub-array
    for (int subidx = 0; subidx < remain; ++subidx, ++arridx)
        list_of_subArrays[subno][subidx] = arr[arridx];

    // advance to next sub-array
    ++subno;
}

更新:

是的,这会将数组划分为 n 个子数组,但不会将其平均划分。假设有一个大小为 10 的数组,并且想将其分成 9 个子数组。那么 8 个子数组将有 1 个原始数组的元素,但一个子数组需要有 2 个元素。

您的原始代码存在一些错误 [已在上述示例中修复]。即使我是为自己做这件事,上述内容也将是让某些事情发挥作用的第一步。

在您最初的问题中,您 确实 说:“每个数组必须具有 大约 相同的大小”。但是,这里有列表子数组的物理大小[仍然是向上取整的值]。

但是,我可能会说“均匀分布”之类的东西,以进一步阐明您的意图。也就是说,您希望最后一个子数组/存储桶是“短”[大幅度]。

鉴于此,代码开始时有些相同,但需要更复杂一些。这还是有点粗糙,可能会进一步优化:

#include <stdio.h>

#ifdef DEBUG
#define dbgprt(_fmt...)     printf(_fmt)
#else
#define dbgprt(_fmt...)     /**/
#endif

int arr[5000];

// Lets call the original integer array with size n: arr
//  n is the size of arr
//  k is the number of subarrays wanted

void
fnc2(int n,int k)
{
    // round up the size of the subarray
    int subsize = (n + (k - 1)) / k;

    int list_of_subArrays[k][subsize];

    dbgprt("n=%d k=%d subsize=%d\n",n,k,subsize);

    int arridx = 0;

    for (int subno = 0;  subno < k;  ++subno) {
        // get remaining number of sub-arrays
        int remsub = k - subno;

        // get remaining number of elements
        int remain = n - arridx;

        // get maximum bucket size
        int curcnt = subsize;

        // get projected remaining size for using this bucket size
        int curtot = remsub * curcnt;

        // if we're too low, up it
        if (curtot < remain)
            ++curcnt;

        // if we're too high, lower it
        if (curtot > remain)
            --curcnt;

        // each bucket must have at least one
        if (curcnt < 1)
            curcnt = 1;

        // each bucket can have no more than the maximum
        if (curcnt > subsize)
            curcnt = subsize;

        // last bucket is the remainder
        if (curcnt > remain)
            curcnt = remain;

        dbgprt("  list[%d][%d] --> arr[%d] remain=%d\n",
            subno,curcnt,arridx,remain);

        // fill next sub-array
        for (int subidx = 0; subidx < curcnt; ++subidx, ++arridx)
            list_of_subArrays[subno][subidx] = arr[arridx];
    }

    dbgprt("\n");
}

【讨论】:

  • 是的,这将数组划分为 n 个子数组,但它并没有平均划分。假设有一个大小为 10 的数组,并且想将其分成 9 个子数组。那么 8 个子数组将有 1 个原始数组的元素,但一个子数组需要有 2 个元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多