这是我试图解决的问题: 我给了一组斜率为m且常数为c的线。现在我需要找到在y轴右侧相交的这些线的交点数。这基本上意味着对于第1行和第2行
c1>c2 and m2>m1
我需要一个O(nlogn)算法来计算y轴右侧的交叉点总数(如果算法存在)。我总是可以通过蛮力来获得o(n2)算法,但我正在寻找更快的算法。
答案 0 :(得分:3)
两个排序的矢量会做到这一点。
排序是n log n。
插入到v2是log n(可以通过自平衡BST实现,它将调用n次)。
二进制搜索是log n(调用n次)。
所以它是O(nlog n)
如果你用C ++写这个,那就像那样(我没有定义v2,因为你将实现自我平衡BST ):
struct line
{
int c,m;
line(int a,int b):c(a),m(b){}
bool operator <(const line &a) const
{
return m>a.m;
}
};
bool cmp(const line &v1,const line &v2)
{
return v1.c<v2.c;
}
int main()
{
vector<line> v1;
v1.push_back(line(1,3));
v1.push_back(line(4,1));
v1.push_back(line(3,1));
v1.push_back(line(2,2));
sort(v1.begin(),v1.end(),cmp);
int ans=0;
for(int i=0;i<v1.size();i++)
{
int num=v2.find(v1[i]);//return the number of element whose m is larger than v1[i].
ans+=num;
v2.insert(v1[i]);// in every step, the element e in v2 will satisfy e.c<v1[i].c
}
cout << ans;
}
这就是全部。如果您有任何疑问,请发表评论。
答案 1 :(得分:0)
我发布了我的解决方案,因为我认为实施起来更简单:
假设你有Line的对象,并定义了以下属性:
- m (slope, initialized on start)
- c (constant, initialized on start)
- pos_m ( default 0 value )
- pos_c ( default 0 value )
现在,您有这些行的V
向量,然后:
V
对m
进行排序。 V
集合i
(O(n))上迭代V[i].pos_m = i
。V
对c
进行排序。 V
集合i
上对V[i].pos_c = i
进行迭代。 (O(N))。result = 0
现在迭代V
索引i
执行result += | V[i].pos_m - V[i].pos_c |
(O(n))在排序时,如果比较值相等,则使用另一个键来确定顺序(如果两者相等,则它们是同一行)。例如,如果在1.两条线具有相同的斜率,则将常量设为决策者。
答案 2 :(得分:-1)
在最坏的情况下,这个问题保证需要O(n ^ 2)次操作。
假设我画了一条线,那么就没有交叉点。我可以在一个独特的点画一条与该线相交的线。我现在可以绘制一条与前两行相交的线。我可以继续绘制与前一行相交的线条。
这意味着交叉点的数量可以达到:
1 + 2 + 3 + 4 + 5 + ... + n-1
如果输入大小为n的行,则此问题的输出大小可以是(N *(N-1))/ 2个点或大约N平方在2以上。
因此,即使只输出正确的答案,在最坏的情况下也需要O(n ^ 2)。
编辑,忽略前一个,我以为你想要实际的交点,而不仅仅是计数。