首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速O(1)算法将连续数均匀分配成连续细分并输出特定的细分边界

快速O(1)算法将连续数均匀分配成连续细分并输出特定的细分边界
EN

Stack Overflow用户
提问于 2021-12-22 06:28:09
回答 3查看 102关注 0票数 1

我有一个由给定的最大数指定的自然数子集。例如,如果给定值为7,则列表为

代码语言:javascript
复制
1,2,3,4,5,6,7

现在,我得到了另一个输入,细分的数量来平均分配列表。对于任何剩余部分,从开始开始,每个细分都会添加一个额外的数字。如果这个数字是3,那么细分的列表将是

代码语言:javascript
复制
[1,2,3][4,5][6,7]

最后给出第三个输入“细分顺序(1和细分数之间)”。在上面的示例中,如果订单为1,则输出为[1,2,3],如果订单为2,则输出为[4,5]

简单的哑方法是先执行7/3=2并计算余数7-2*3=1,然后通过首先分配1,2生成第一个组,然后由于第一个组顺序不大于余数,添加一个元素get 1,2,3。然后生成第二组,等等。

然而,在我看来,必须有一种方法可以直接获得一个中间组,而不需要生成所有以前的组。也就是说,在没有经过for循环的情况下,获得[6,7]给出输入max_num=7, subdivision_num=3, subdivision_order=3

现在实际的细分输出仅用最小和最大的数来表示(即7,3,1的输出是1,3),因此后者意味着一个最坏的O(1)算法,而普通的愚蠢方法有最坏的情况O(n),其中n是细分数。

这似乎不太困难,但我挣扎了一段时间,无法提出“直接O(1)”算法。任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-12-22 07:00:34

不考虑生成列表的时间,假设分支和算术操作需要恒定的时间,我们可以在O(1)中完成。

代码语言:javascript
复制
parts = max_num // subdivisions_num
rems = max_num % subdivisions_num
if subdivision_order < rems:
  startindex = (parts+1) * (subdivision_order - 1)
  length = parts + 1
  print(numlist[startindex:startindex+length])
else:
  startindex = (parts+1) * rem + parts * (subdivision_order - rem - 1)
  length = parts
  print(numlist[startindex:startindex+length])

我想你不需要把列表划分成子列表。您可以只计算子数组的开始和长度。

在这种情况下,如果~subdivision_order~小于~max_num~和~subdivision_num~的其余部分,则只需将~subdivision_order -1(在0-索引的情况下)乘以~max_num // subdivision_num~,长度将为~max_num // subdivision_num +1。

票数 3
EN

Stack Overflow用户

发布于 2021-12-22 06:53:04

如果我正确理解你的问题,你会得到三个值

  • maximum
  • segments
  • segment索引(基于一个)

并且您希望返回段范围的最小值和最大值。

让我们来看一个稍微大一点的例子

  • 最大值=107个
  • 段=10
  • 段指数= 4

好吧,算一算

代码语言:javascript
复制
107 (maximum) / 10 (segments) = 10 values in a segment with 7 left over.

因此,前7个段有11个值,最后3个部分有10个值。剩下的在第一段。

所以3 * 11 = 33。3是零基段索引,前3段有11个值,

第4段也有11个值,所以您将返回33 +1和33 + 11,或34和44。唯一的“诀窍”是确保区分带有余数的段和不带余数的段。

你需要计算四个数字。有余数的段数,带余数的段的长度,没有余数的段数,没有余数的段的长度。

在我给出的例子中,将是7& 11,3& 10,然后添加前几段的计数和想要的段的计数。你用两个乘法来完成这个任务。

第一个乘法是余数段数乘以余数段长度。第二个乘法是非剩余段的数量乘以非剩余段的长度。

再一次,用我给出的例子,那就是

代码语言:javascript
复制
3 * 11 + 0 * 10 = 33

其中3是基于零的段索引,11是余数段的长度,0是非剩余段的数目,10是非剩余段的长度。

复杂度为O(1)。

票数 3
EN

Stack Overflow用户

发布于 2021-12-22 07:36:44

下面是该算法在JavaScript片段中的一个实现。您可以交互地输入参数来测试它。

代码语言:javascript
复制
function partition(size, partitionCount, partitionPosition) {
    if (partitionCount < 1 || partitionCount > size) return null; // Out of range
    if (partitionPosition < 1 || partitionPosition > partitionCount) return null; // Out of range
    // Get the largest partition size
    let partitionSize = Math.ceil(size / partitionCount);
    // Determine how many partitions are that large
    let largerPartitionCount = partitionCount - (partitionSize - size % partitionSize) % partitionSize;
    // Convert 1-based position to 0-based index
    let partitionIndex = partitionPosition - 1;
    // Derive the first and last value of the requested partition
    let first = partitionIndex * partitionSize + 1 - Math.max(0, partitionIndex - largerPartitionCount);
    let last = first + partitionSize - 1 - (partitionIndex >= largerPartitionCount ? 1 : 0);
    return [first, last];
}

// I/O management

let inputs = document.querySelectorAll("input");
let output = document.querySelector("span");

document.addEventListener("change", refresh);

function refresh() {
    let [size, partitionCount, partitionPosition] = Array.from(inputs, input => +input.value);
    let result = partition(size, partitionCount, partitionPosition);
    output.textContent = JSON.stringify(result);
}

refresh();
代码语言:javascript
复制
input { width: 3em }
代码语言:javascript
复制
Array size: <input type="number" value="7" ><br>
Number of partitions: <input type="number" value="3" ><br>
Partition to return: <input type="number" value="1" ><br>
<br>
Returned partition: <span></span>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70445048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档