计算直角三角形:如何提高时间复杂度?

时间:2018-07-23 14:33:01

标签: c++ optimization

这是我正在研究的问题:

  

N个点放置在坐标平面中。

     

编写一个程序,计算出我们可以选择三种方式的数量   点,以便它们形成一个直角三角形,其腿平行于   坐标轴。

直角三角形具有一个90度的内角。直角三角形的腿是两个短边。

这是我组织代码的方式。

对于每一点,我都检查了另一点。如果两个点具有匹配的x坐标和不同的y坐标,那么我将遍历这些点以查找具有与新点相同的y坐标和不同的x的点。如果发现,我检查了三个点是否有直角的斜边。

类似地,我对两个点重复了修改,这些点具有匹配的y坐标和不同的x。

该程序可以运行,但是会浪费时间,而且我不确定如何减少它。

这是我的代码:

double distwithoutroot(int x1, int y1, int x2, int y2) {
    int xdist = pow((x2 - x1),2);
    int ydist = pow((y2 - y1),2);
    return  xdist + ydist;
}

int main() {
    int noofpoints;

    cin >> noofpoints;
    int xs[100000];
    int ys[100000];
    int count = 0;

    for (int i = 0; i < noofpoints; i++) {
        cin >> xs[i] >> ys[i];
    }

    for (int i = 0; i < noofpoints; i++) {
        int main_x_point = xs[i];
        int main_y_point = ys[i];

        for (int j = 0; j < noofpoints; j++) {
            int checkmatchx = xs[j];
            int checkmatchy = ys[j];

            if (main_x_point == checkmatchx && main_y_point != checkmatchy) {

                for (int k = 0; k < noofpoints; k++) {
                    int secondcheckx = xs[k];
                    int secondchecky = ys[k];

                    if (checkmatchy == secondchecky && checkmatchx != secondcheckx) {
                        int hypotenus = distwithoutroot(main_x_point, main_y_point, secondcheckx, secondchecky);

                        int perpendicular = distwithoutroot(main_x_point, main_y_point, checkmatchx, checkmatchy);
                        int base = distwithoutroot(secondcheckx, secondchecky, checkmatchx, checkmatchy);
                        if (hypotenus== ( perpendicular+ base )) {
                            count += 1;
                            }
                        }
                }
            }

            else if (main_y_point == checkmatchy && main_x_point != checkmatchx) {
                for (int k = 0; k < noofpoints; k++) {
                    int secondcheckx = xs[k];
                    int secondchecky = ys[k];
                    if (checkmatchx == secondcheckx && checkmatchy != secondchecky) {
                        int hypotenus = distwithoutroot(main_x_point, main_y_point, secondcheckx, secondchecky);
                        int base = distwithoutroot(main_x_point, main_y_point, checkmatchx, checkmatchy);
                        int perpendicular = distwithoutroot(secondcheckx, secondchecky, checkmatchx, checkmatchy);
                        if (hypotenus == (perpendicular + base)) {
                            count += 1;
                        }
                    }
                }
            }


        }

        cout<<count;

    }

2 个答案:

答案 0 :(得分:2)

您只需要将所有点放在x和y的两个地图中。运行时间减少为O(N)* O(T),T是同一拐角处三角形的最大值。

答案 1 :(得分:0)

扩展the other answer中的想法。

请注意,无需检查勾股定理。如果三角形有一个水平边和一个垂直边,则它是一个直角三角形。要计算此类三角形的数量,只需要使X和Y坐标等于任何值的点数即可。

因此,一个代码草图:

std::map<int, int> map_x; // for each X, counts the points for which xs = X
std::map<int, int> map_y; // for each Y, counts the points for which ys = Y

for (int i = 0; i < noofpoints; i++)
    ++map_x[xs[i]];

for (int i = 0; i < noofpoints; i++)
    ++map_x[ys[i]];

for (int i = 0; i < noofpoints; i++)
    count += (map_x[xs[i]] - 1) * (map_y[ys[i]] - 1);

最后一个循环的说明:

迭代所有点,并计算该点在直角位置处的直角三角形的数量。

对于每个点,它知道多少个点具有相同的X和多少个点具有相同的Y(必须减去1来排除相同的点)。这些的每种组合都会给出一个合适的三角形。

顺便说一句,某些三角形可能会退化(面积为零);同样,如果某些点出现两次,则某些三角形可能是相同的。我认为您不应该将这些排除在外。