如何从哈希表中获取第二大的距离?

huangapple go评论70阅读模式
英文:

How to get second biggest distance from a Hashmap?

问题

我正试图在Java中的哈希映射中获取最大和第二大的距离。

基本上,从一个包含(x,y)值的哈希映射中,我计划选择一个点,将其设置为固定点,并计算与所有其他点相关的距离。在计算了所有可能的距离之后,我将固定点更改为哈希映射中的下一个元素。通过这个过程,我旨在在哈希映射中按距离获取最大和第二大的值。

HashMap<Integer, Integer> corners = getPotentialCorners(image);
HashMap<Integer, Integer> extremeCorners = new HashMap<>();
int Blue = new Color(0, 0, 255).getRGB();
int currentNumberX;
int currentNumberY;
int pivotVarX;
int pivotVarY;
double distance;
double Highest = 0;
double Highest2 = 1;
int xHighest = 0;
int yHighest = 0;
int xHighest2 = 0;
int yHighest2 = 0;
for (int i : corners.keySet()) {
    currentNumberX = (i);
    currentNumberY = corners.get(currentNumberX);
    for (int j : corners.keySet()) {
        pivotVarX = j;
        pivotVarY = corners.get(pivotVarX);
        distance = Math.abs(Math.sqrt(Math.pow((pivotVarX - currentNumberX), 2) + Math.pow((pivotVarY - currentNumberY), 2)));
        if (pivotVarX != currentNumberX) {
            if ((Highest > Highest2)) {
                xHighest = currentNumberX;
                yHighest = currentNumberY;
                Highest2 = distance;
            }
            if (distance > Highest2) {
                Highest2 = distance;
                xHighest2 = currentNumberX;
                yHighest2 = currentNumberY;
            }
        }
    }
}

通过这段代码,我进行了调试,我总是得到一个正确的点,而另一个点总是(0,0)。我知道问题在于获取第二高点(Highest2、XHighest2、YHighest2)的过程,但我不知道如何修复它。

英文:

I am trying to get the biggest and second biggest distance in a Hashmap in Java.

Basically, from a hashmap populated with (x,y) values, I plan to pick a point, set it as a fixed point and calculate distance with this point in relation to all the other points. After all possible distances are calculated, I change the fixed point to the next element in the HashMap. With this process, I aim to get the biggest and second biggest value in a hashmap distance-wise.

 HashMap&lt;Integer, Integer&gt; corners = getPotentialCorners(image);
        HashMap&lt;Integer, Integer&gt; extremeCorners = new HashMap&lt;&gt;();
        int Blue = new Color(0, 0, 255).getRGB();
        int currentNumberX;
        int currentNumberY;
        int pivotVarX;
        int pivotVarY;
        double distance;
        double Highest = 0;
        double Highest2 = 1;
        int xHighest = 0;
        int yHighest = 0;
        int xHighest2 = 0;
        int yHighest2 = 0;
        for (int i : corners.keySet()) {
            currentNumberX = (i);
            currentNumberY = corners.get(currentNumberX);
            for (int j : corners.keySet()) {
                pivotVarX = j;
                pivotVarY = corners.get(pivotVarX);
                distance = Math.abs(Math.sqrt(Math.pow((pivotVarX - currentNumberX), 2) + Math.pow((pivotVarY - currentNumberY), 2)));
                if (pivotVarX != currentNumberX) {
                    if ((Highest &gt; Highest2)) {
                        xHighest = currentNumberX;
                        yHighest = currentNumberY;
                        Highest2 = distance;
                    }
                    if (distance &gt; Highest2) {
                        Highest2 = distance;
                        xHighest2 = currentNumberX;
                        yHighest2 = currentNumberY;
                    }


                }
            }


        }

With this code, I debugged it, and I always get one correct point, and another point is ALWAYS (0,0). I know the issue lies with my process of getting the second highest point (Highest2, XHighest2,YHighest2), but I do not know how to fix it.

答案1

得分: 1

正如其他人指出的那样,与其使用HashMap,最好使用List<Point>,你可以轻松地进行迭代:

for (Point p: myList) {
   ...
}

或者如果你需要更多地控制要迭代的元素,你可以使用整数计数器:

for (int j = i+1; j < corners.size(); j++) {
   Point p = corners.get(j);
   ...
}

而不是必须使用keySet()get(),以及在相同的 bin 上具有相同 x 值映射时出现的所有问题。

另外,还有一些微小的速度改进可以实现:

  • 无需使用缓慢的Math.sqrt()函数(或Math.abs(),因为平方根始终为正数),因为你只是在比较较大/较小的距离。你可以直接比较平方距离。
  • 最新的Java编译器知道如何优化Math.pow(int, 2),但为了确保你不会得到函数调用的开销,你可以通过编写:(p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.x-q.y)来帮助编译器。

currentpivot重命名为pq以减少代码长度,你的代码将会是这样的:

List<Point> corners = getPotentialCorners(image);
Double highest = null;
Double highest2 = null;
Point highestP = null, highestQ = null;
Point highestP2 = null, highestQ2 = null;
for (int i = 0; i < corners.size()-1; i++) {
    Point p = corners.get(i);
    for (int j = i+1; j < corners.size(); j++) {
        Point q = corners.get(j);
        double distanceSq = (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
        if (highest == null || distanceSq >= highest) {
            // shift highest to second highest
            highest2 = highest;
            highestP2 = highestP;
            highestQ2 = highestQ;

            highest = distanceSq;
            highestP = p;
            highestQ = q;
        } else if (highest2 == null || distanceSq > highest2) {
            highest2 = distanceSq;
            highestP2 = p;
            highestQ2 = q;
        }
    }
}
英文:

As others pointed out, instead of a HashMap, it is better to use List&lt;Point&gt; which you can easily iterate as:

for (Point p: myList) {
...
}

or if you need more control on which elements to iterate over you can use an integer counter:

for (int j = i+1; j &lt; corners.size(); j++) {
Point p = corners.get(j);
...
}

instead of having to use keySet() and get() and all the problems with identical x-values mapping on the same bin.

Also, there are some trivial speed improvements possible:

  • No need to use the slow Math.sqrt() function (or Math.abs() as square root is always positive) since you are only comparing larger/smaller distances. You can just compare the squared distances.
  • The latest Java compiler knows how to optimize Math.pow(int, 2), but to make sure you don't get the overhead of a function call, you can help the compiler by writing: (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.x-q.y)

Renaming current and pivot to p and q for conciseness, your code would look like:

List&lt;Point&gt; corners = getPotentialCorners(image);
Double highest = null;
Double highest2 = null;
Point highestP = null, highestQ = null;
Point highestP2 = null, highestQ2 = null;
for (int i = 0; i &lt; corners.size()-1; i++) {
Point p = corners.get(i);
for (int j = i+1; j &lt; corners.size(); j++) {
Point q = corners.get(j);
double distanceSq = (p.x-q.x)*(p.x-q.x) + (p.y-q.y)*(p.y-q.y);
if (highest == null || distanceSq &gt;= highest) {
// shift highest to second highest
highest2 = highest;
highestP2 = highestP;
highestQ2 = highestQ;
highest = distanceSq;
highestP = p;
highestQ = q;
} else if (highest2 == null || distanceSq &gt; highest2) {
highest2 = distanceSq;
highestP2 = p;
highestQ2 = q;
}
}
}

huangapple
  • 本文由 发表于 2020年8月31日 08:05:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/63663255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定