寻找罗盘标题数组的最大差异

时间:2018-03-29 03:06:21

标签: algorithm math distance

我试图拥有"范围"最后X秒的指南针标题。示例:在最后一分钟,我的标题在指南针上介于120deg和140deg之间。够容易吧?我有一个带有指南针标题的数组在这段时间内,比如每秒读一次。

[ 125, 122, 120, 125, 130, 139, 140, 138 ]

我可以使用最小值和最大值,然后你就可以了。我的范围是从120到140。

除此之外并非如此简单。举例来说,如果我的标题从10度转移到350度(即#34;通过"通过北方,改变-20度。

现在我的数组看起来像这样:

[ 9, 10, 6, 3, 358, 355, 350, 353 ]

现在Min 3且最大358 ,这不是我需要的:(我正在寻找最多"右手"(顺时针)值,大多数"左手"(逆时针)值。

我能想到的唯一方法是找到沿着圆圈的最大弧线,其中不包括阵列中的任何值,但我甚至不知道如何做到这一点。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

问题分析

总结一下这个问题,听起来你想要找到以下两个方面:

  1. 最接近的两个读数(为简单起见:顺时针方向)AND
  2. 包含它们之间的所有其他读数。
  3. 所以在你的第二个例子中,9和10只相差1°,但它们并不包含所有其他读数。相反,顺时针方向从10到9将包含所有其他读数,但它们在该方向上相隔359°,因此它们不是最接近的。

    在这种情况下,我不确定使用最小和最大读数是否有帮助。相反,我建议对所有读数进行排序。然后,您可以更轻松地检查上面指定的两个条件。

    以下是您提供的第二个示例,按升序排序:

    [ 3, 6, 9, 10, 350, 353, 355, 358 ]

    如果我们从头开始,我们知道从阅读3到阅读358将包含所有其他读数,但它们相距358 - 3 = 355°。我们可以继续逐步扫描结果。请注意,一旦我们绕圈,我们必须添加360以正确计算分离度。

    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
      *-------------------------->               358 -   3 = 355° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ->   *-----------------------------  (360 +   3) -   6 = 357° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ---->   *--------------------------  (360 +   6) -   9 = 357° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ------->   *-----------------------  (360 +   9) -  10 = 359° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ---------->    *-------------------  (360 +  10) - 350 =  20° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    -------------->     *--------------  (360 + 350) - 353 = 357° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ------------------->     *---------  (360 + 353) - 355 = 358° separation
    
    [ 3, 6, 9, 10, 350, 353, 355, 358 ]
    ------------------------>     *----  (360 + 355) - 358 = 357° separation
    

    伪代码解决方案

    这是用于确定读取值的最小程度范围的伪代码算法。如果考虑到性能,肯定有一些方法可以优化。

    // Somehow, we need to get our reading data into the program, sorted
    // in ascending order.
    // If readings are always whole numbers, you can use an int[] array
    // instead of a double[] array.  If we use an int[] array here, change
    // the "minimumInclusiveReadingRange" variable below to be an int too.
    double[] readings = populateAndSortReadingsArray();
    
    if (readings.length == 0)
    {
      // Handle case where no readings are provided.  Show a warning,
      // throw an error, or whatever the requirement is.
    }
    else
    {
    
      // We want to track the endpoints of the smallest inclusive range.
      // These values will be overwritten each time a better range is found.
      int minimumInclusiveEndpointIndex1;
      int minimumInclusiveEndpointIndex2;
      double minimumInclusiveReadingRange;  // This is convenient, but not necessary.
                                            // We could determine it using the
                                            // endpoint indices instead.
    
      // Check the range of the greatest and least readings first.  Since
      // the readings are sorted, the greatest reading is the last element.
      // The least reading is the first element.
      minimumInclusiveReadingRange = readings[array.length - 1] - readings[0];
      minimumInclusiveEndpointIndex1 = 0;
      minimumInclusiveEndpointIndex2 = array.length - 1;
    
      // Potential to skip some processing.  If the ends are 180 or less
      // degrees apart, they represent the minimum inclusive reading range.
      // The for loop below could be skipped.
    
      for (int i = 1; i < array.length; i++)
      {
        if ((360.0 + readings[i-1]) - readings[i] < minimumInclusiveReadingRange)
        {
          minimumInclusiveReadingRange = (360.0 + readings[i-1]) - readings[i];
          minimumInclusiveEndpointIndex1 = i;
          minimumInclusiveEndpointIndex2 = i - 1;
        }
      }
    
      // Most likely, there will be some different readings, but there is an
      // edge case of all readings being the same:
      if (minimumInclusiveReadingRange == 0.0)
      {
        print("All readings were the same: " + readings[0]);
      }
      else
      {
        print("The range of compass readings was: " + minimumInclusiveReadingRange +
              " spanning from " + readings[minimumInclusiveEndpointIndex1] +
              " to " + readings[minimumInclusiveEndpointIndex2]);
      }
    
    }
    

    这个伪代码算法没有覆盖一个额外的边缘情况,并且存在多个最小包含范围的情况......

    • 示例1:[0,90,180,270],其范围为270(90至0/360,180至90,270至180和0至270)。
    • 实施例2:[85,95,265,275],其范围为190(85至275和265至95)

    如果需要报告创建最小包含范围的每对可能端点,则此边缘情况会稍微增加逻辑的复杂性。如果重要的是确定最小包含范围的值,或者只报告一对代表最小包含范围就足够了,那么提供的算法就足够了。

相关问题