【问题标题】:How to return the correct value when Divide and Conquer Algorithm(for 1-D Closest Pairs) has done its job?当分而治之算法(对于一维最近对)完成其工作时,如何返回正确的值?
【发布时间】:2015-02-11 19:53:33
【问题描述】:

我需要找到一个整数数组中最接近的一对数字。例如:如果我有 {25, 13, 59, 7, 16} 个数字,我的结果应该是 |13 - 16| = 3. 所以我尝试使用分治算法来解决这个问题。但是当我从子问题中得到数字差异时,我无法存储和比较它们。当我调试它时,我看到我的程序出错了,但几个小时都找不到任何解决方案。

这是我的功能:

int closestPairs(int list[], int first, int last)
{
    if (last - first == 1)
        return 0;
    else if (last - first == 2)
        return abs(list[first] - list[last - 1]);

    int median = (first + last) / 2;

    int left = closestPairs(list, first, median);
    int right = closestPairs(list, median, last);

    int temp = abs(list[first] - list[last - 1]);

    if (abs(left - right) < temp)
        temp = abs(left - right);

    return temp;
}

这里是驱动函数:

int main()
{
    int list[] = { 34, 23, 48 , 4, 66, 69};
    int n = sizeof(list) / sizeof(int);
    cout << closestPairs(list, 0, n) << endl;

    return 0;
}

那么如何存储从 abs(left - right) 获得的值并查看它是否小于或大于下一个值?还是我完全错了,做的一切都错了?提前致谢。

【问题讨论】:

  • 我认为你的算法不正确。
  • 如果您能说明错误的原因,我将不胜感激。我被这个问题困了几个小时,我的大脑快要爆炸了。 :)
  • 你必须使用分而治之算法吗?
  • 是的,我可以使用迭代算法来做到这一点,但在这种情况下我需要使用递归。

标签: c++ algorithm divide-and-conquer


【解决方案1】:

在我看来,在这种情况下,使用递归来找到解决方案并存储一个值以与下一次迭代进行比较的概念是相反的概念。在递归函数中存储用于比较的变量似乎有点混乱(并且需要对代码进行一些重大的重组)。据我了解,您的分而治之算法的想法是获取一个大整数列表并将其划分为较小的列表,并允许最佳答案通过链向上。这是我根据您的代码看到的工作方式(主要使用伪代码):

int FindClosest(int list[],int first,int last)
{
     if(number of elements in list == 2)
     {
         return (int2 - int1)
     }
     if(number of elements in list == 3){
     {
         if((int3-int2)<(int2 - int2))
             return (int3-int2)
         else
             return (int2-int1)
     }
     if(number of elements in list >3)
     {
         subList1 = oneSubGroupofElements(list)
         subList2 = anotherSubGroupofelements(list)
         if(FindClosest(subList1)<FindClosest(subList2))
              return Findclosest(subList1)
         else
              return FindClosest(subList2)
     }
}

这个方法还有一个问题,你可以看到超过 2 个元素的列表,因为你的结果依赖于成对的邻居,你必须考虑你不能把列表分成两半。例如:

int list[] = {1,4,5,9}

如果您只是将列表拆分为两个元素的两个列表,则会导致问题,因为不会考虑 4 和 5 之间的差异(这将是正确的答案)。您的子列表必须包含重叠部分,以便在从 FindClosest 调用时,至少有一个子列表返回 5-4。

【讨论】:

  • 谢谢,你拯救了我的一天。 :)
【解决方案2】:

您必须先对列表进行排序,然后才能使用分而治之的技术找到最接近的配对。因为这消除了许多极端情况。

【讨论】:

  • 我已手动将列表更改为排序形式,但结果仍然不正确。当 temp 被定义但无法弄清楚为什么以及解决方案是什么时,问题就开始了。
  • 是的,您不需要“temp”,您只需要返回“right”和“left”中最小的那个。此外,在您的停止条件下,您应该处理这种情况,如果 last==first 并为此返回 INT_MAX(在标题 climits 中定义)。此外,对于 last-first ==1 的情况,您应该将距离返回为 INT_MAX 而不是 0)。
猜你喜欢
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 2017-08-19
  • 2013-02-02
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 2019-04-08
相关资源
最近更新 更多