我有一个由给定的最大数指定的自然数子集。例如,如果给定值为7,则列表为
1,2,3,4,5,6,7现在,我得到了另一个输入,细分的数量来平均分配列表。对于任何剩余部分,从开始开始,每个细分都会添加一个额外的数字。如果这个数字是3,那么细分的列表将是
[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)”算法。任何帮助都将不胜感激。
发布于 2021-12-22 07:00:34
不考虑生成列表的时间,假设分支和算术操作需要恒定的时间,我们可以在O(1)中完成。
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。
发布于 2021-12-22 06:53:04
如果我正确理解你的问题,你会得到三个值
并且您希望返回段范围的最小值和最大值。
让我们来看一个稍微大一点的例子
好吧,算一算
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,然后添加前几段的计数和想要的段的计数。你用两个乘法来完成这个任务。
第一个乘法是余数段数乘以余数段长度。第二个乘法是非剩余段的数量乘以非剩余段的长度。
再一次,用我给出的例子,那就是
3 * 11 + 0 * 10 = 33其中3是基于零的段索引,11是余数段的长度,0是非剩余段的数目,10是非剩余段的长度。
复杂度为O(1)。
发布于 2021-12-22 07:36:44
下面是该算法在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();input { width: 3em }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>
https://stackoverflow.com/questions/70445048
复制相似问题