Algorithm 查找数组中角度之间的最大差异

Algorithm 查找数组中角度之间的最大差异,algorithm,math,accelerometer,Algorithm,Math,Accelerometer,我正在处理一些加速度计数据,它是一个介于-180和180之间的值数组。用度表示角度 有没有一个聪明的算法可以找出任意两个角度之间的最大差异?为了解决这个问题,应该有很多角度。当然,你可以打败O(n^2) 对数组进行排序。使用指针a和b逐步完成。首先找到与a形成最大角度的b,并将其存储到best。然后重复将a向前推进一步,然后执行b,直到停止增加差值。由于b无法跨过a,因此您将遍历该列表大约1.5倍的总和,以O(n)为界。因此,排序所需的时间并不比排序所需的时间更糟糕。为了担心这一点,应该有很多角

我正在处理一些加速度计数据,它是一个介于-180和180之间的值数组。用度表示角度


有没有一个聪明的算法可以找出任意两个角度之间的最大差异?

为了解决这个问题,应该有很多角度。当然,你可以打败O(n^2)


对数组进行排序。使用指针
a
b
逐步完成。首先找到与
a
形成最大角度的
b
,并将其存储到
best
。然后重复将
a
向前推进一步,然后执行
b
,直到停止增加差值。由于
b
无法跨过
a
,因此您将遍历该列表大约1.5倍的总和,以O(n)为界。因此,排序所需的时间并不比排序所需的时间更糟糕。

为了担心这一点,应该有很多角度。当然,你可以打败O(n^2)


对数组进行排序。使用指针
a
b
逐步完成。首先找到与
a
形成最大角度的
b
,并将其存储到
best
。然后重复将
a
向前推进一步,然后执行
b
,直到停止增加差值。由于
b
无法跨过
a
,因此您将遍历该列表大约1.5倍的总和,以O(n)为界。因此,它并不比排序所需的时间差。

假设角度在[0,180]时为正,如果在[-180,0]时为负

扫描列表,执行以下操作:
1记录最大和最小正角度
2记录最大和最小负角度
3如果一个角度是正角度,将其转换(让它减去180)为负角度,并用一些标志标记它以指示它来自转换

对于#1,最大的差异就是最大角度减去最小角度。#2也是如此

对于#3,首先对角度进行排序。从已排序列表的末尾扫描。如果相邻角度的类型不同(一个是转换角度,一个不是),则计算差异。如果差异是有史以来最小的,记录下来,然后继续扫描。完成后,使用180-差,结果为差#3

现在您有3个差异,选择最大的一个。我想这就是答案


对于复杂性,所有扫描都是O(n)。对于排序,如果所有角度都为正或负,则根本不需要相位#3。如果需要相位#3,我们可以让它有更小的角度。例如,如果列表的正角度较少,则可以将正角度转换为负角度,反之亦然。排序是O(nlgn),但我们可以有更小的n。

如果角度在[0,180]中,它是正的,如果在[-180,0]中,它是负的

扫描列表,执行以下操作:
1记录最大和最小正角度
2记录最大和最小负角度
3如果一个角度是正角度,将其转换(让它减去180)为负角度,并用一些标志标记它以指示它来自转换

对于#1,最大的差异就是最大角度减去最小角度。#2也是如此

对于#3,首先对角度进行排序。从已排序列表的末尾扫描。如果相邻角度的类型不同(一个是转换角度,一个不是),则计算差异。如果差异是有史以来最小的,记录下来,然后继续扫描。完成后,使用180-差,结果为差#3

现在您有3个差异,选择最大的一个。我想这就是答案


对于复杂性,所有扫描都是O(n)。对于排序,如果所有角度都为正或负,则根本不需要相位#3。如果需要相位#3,我们可以让它有更小的角度。例如,如果列表的正角度较少,则可以将正角度转换为负角度,反之亦然。排序是O(nlgn),但我们可以有更小的n。

从RW教程中得到了这一点

它与您想要的相反(返回最小角度),但您可以调整它

// Returns shortest angle between two angles,
// between -M_PI and M_PI

static inline CGFloat ScalarShortestAngleBetween(const CGFloat a, const CGFloat b)
{
    CGFloat difference = b - a;
    CGFloat angle = fmodf(difference, M_PI * 2);
    if (angle >= M_PI)
    {
        angle -= M_PI * 2;
    }
    return angle;
}

这是从RW教程中得到的

它与您想要的相反(返回最小角度),但您可以调整它

// Returns shortest angle between two angles,
// between -M_PI and M_PI

static inline CGFloat ScalarShortestAngleBetween(const CGFloat a, const CGFloat b)
{
    CGFloat difference = b - a;
    CGFloat angle = fmodf(difference, M_PI * 2);
    if (angle >= M_PI)
    {
        angle -= M_PI * 2;
    }
    return angle;
}

聪明?你的意思是对它们进行排序,然后取a[1]和a[N]数据是循环的,180=-180。因此,仅找到最小值和最大值是不够的。因此,请先转换,然后排序。定义“最大差异”?例如,角度X和角度X之间最大的区别是什么?是0吗?是360吗?它是360的特定整数倍吗?角度X和它本身之间的差是0。我们正在寻找一对相距最接近180度的组合(因为不可能得到更多)。聪明吗?你的意思是对它们进行排序,然后取a[1]和a[N]数据是循环的,180=-180。因此,仅找到最小值和最大值是不够的。因此,请先转换,然后排序。定义“最大差异”?例如,角度X和角度X之间最大的区别是什么?是0吗?是360吗?它是360的特定整数倍吗?角度X和它本身之间的差是0。我们正在寻找最接近180度的一对(因为不可能得到更多)。我认为你在这里得到了正确的答案,但需要更多的解释来将其与“排序并选择第一个和最后一个”建议分开。例如,您可以说明为什么对于排序数组
a
,如果
a[j]
a[i]
的角度差最大,
a[k]
a[i+1]
的角度差最大,
k>=j
。这就是为什么你不必搜索O(n^2)对。我认为你在这里得到了正确的答案,但需要更多的解释才能将其与“排序并选择第一个和最后一个”建议分开。例如,您可以说明为什么对于排序数组
a
,如果
a[j]
的角度最大