【发布时间】:2022-08-19 19:07:19
【问题描述】:
介绍
再会,
我正在寻找一种可以执行以下操作的分组算法:
假设我有一个排序数字数组(没有多次出现)。例如,{0、2、5、6、7、10}。
我想从该数组中创建组,例如:
- 尽量减少组数,
- 每个组需要包含最多链接的数字n - 1\"bonds\"(例如,n = 3, 0 和 2 是邻居,但不是 0 和 3)。
编辑
换句话说,当我说邻居时,我应该说整数距离。例如,0 到 2 i 2 的距离(反之亦然)。 0 到 3 的距离为 3。您可以将问题想象为一组 1D 点,需要找到最少数量的中心,其中中心包含距离它为 n/2 的点。我希望这样更清楚。
该示例可能有多个组,但条件 1 和 2 (n = 3) 的最佳值是 {{0, 2}, {5, 6, 7}, {10}}。 {{0}, {2, 5}, {6, 7}, {10}} 比最佳解决方案多一组。如果所有排序的数字都是连续的,那么理想的解决方案就会发生:
nb_groups* = ceil(v.size() / n);此外,根据算法,可能有多种解决方案。
我试过的
目前,我要做的是:
- 计算相邻元素之间的距离数组,
- 检查从向量开头到结尾的休止符的相邻条件(参见下面的代码)。
它似乎工作(对我来说),但我想知道两件事:
- 它真的适用于任何情况吗(可能没有测试所有情况?)?
- 如果是这样,我能否以某种方式优化我的实现(优于 in.size() - 1 次迭代和更少的内存消耗)?
代码
我正在考虑一个将向量分组的函数,以及最大距离。此函数将返回组的第一个元素的索引。
#include <iostream> #include <vector> std::vector<int> groupe(const std::vector<int>& at, const int& n); int main() { // Example of input vector std::vector<int> in = {0, 2, 5, 6, 7, 10, 11, 22, 30, 50, 51}; // Try to group with neighbouring distance of 3 std::vector<int> res = groupe(in, 3); // Printing the result for(const int& a : res) { std::cout << a << \" \"; } } std::vector<int> groupe(const std::vector<int>& at, const int& n) { std::vector<int> out; // Reste keeps tracks of a bigger neighbouring distance (in case we can look for another element to be in the group) int reste(0); size_t s = at.size() - 1; for(int i = 0; i < s; i++) { // Computing the distance between element i and i + 1 int d = at[i + 1] - at[i]; if(d >= n) { if(reste == 0) { out.push_back(i); } reste = 0; } else { if(reste == 0) { out.push_back(i); } reste += d; if(reste >= n) { reste = 0; } } } if(reste == 0 || reste >= n) { out.push_back(s); } return out; }输出
0 2 5 7 8 9
笔记
如果原始向量没有排序,我想我们可以先对其进行排序,然后再完成这一步(或者可能有另一种更有效的算法?)。
我提前感谢您的时间和帮助。
-
它不太清楚你对“债券”的意思。 \"(例如,n = 3, 0 和 2 是邻居,但不是 0 和 3)。\" 嗯?!? 3,0 和 2 是邻居,但 0 和 3 不是?为什么?
-
抱歉,如果这不清楚。我的意思是从 0 到 2 的距离是 2 \"bonds\" (2 - 0)。而对于 0 和 3,这是 3 (3 - 0)。
-
你有一个简单的贪心算法会失败的例子吗? seems to work ok。我找不到贪心算法不能提供最佳解决方案的例子。
-
@MarekR 现在不是,如果您能看到一个失败的案例,那是我的问题的一部分。好的,谢谢,那么我的第一个问题似乎得到了回答。您是否看到任何优化改进?