• 10. Max Points on a Line


    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

    主要思想:O(n2),固定一个点,遍历其余 n 个点, 计算与该点相同的点的个数,和其余所有点的斜率,相同斜率的点视为同一直线。

    初步 AC 代码:

    /**
     * Definition for a point.
     * struct Point {
     *     int x;
     *     int y;
     *     Point() : x(0), y(0) {}
     *     Point(int a, int b) : x(a), y(b) {}
     * };
     */
    class Solution {
    public:
        int maxPoints(vector<Point> &points) {
            unordered_map<float, int> mp;
            int maxNumber = 0;
            for(size_t i = 0; i < points.size(); ++i) {
                int repeat = 1;
                int sameX = 0;
                for(size_t j = 0; j < points.size(); ++j) {
                    if(j == i) continue;
                    if(points[j].x == points[i].x) {
                        if(points[j].y == points[i].y) ++repeat;
                        else ++sameX;
                    } 
                    else {
                        float k = (float)(points[i].y - points[j].y) / (points[i].x - points[j].x);// key.
                        mp[k]++;
                    }
                }
                unordered_map<float, int>::iterator it = mp.begin();
                while(it != mp.end()) {
                    if(it->second + repeat > maxNumber) maxNumber = it->second + repeat;
                    ++it;
                }
                maxNumber = (repeat + sameX) > maxNumber ? (repeat + sameX) : maxNumber;
                mp.clear();
            }
            return maxNumber;
        }
    };
    

    但是里面的 hash map 使用了 浮点值做键值是个非常拙劣的方法。如下所述:

    Testing equality with float ou double is always a bad idea because of rounding errors, so don't use them as a hash. Never.

    For it's floating point arithmetic, Java uses a subset of IEEE754. IEEE754 is full of beautiful tricks to mimic the behavior of real numbers and do a wonderful job at it, so sometimes we forget that is has limitations. The main troubles are (in no specific order):

    • there is a gap between 0.0 and the next value (so non-zero numbers can be rounded to 0 if they are in this gap)
    • there are special values for +infinity and -infinity (so there is no overflow, but you can get "stuck" on an infinite value. Imagine a*b evaluates to infinity, then a*b/bwill also evaluate to infinity and not to à`)
    • there is a special value NaN that means not a number. (0.0 / 0.0 evaluates to NaN)
    • there are signed zeroes  (+0.0 and -0.0) Signed zeroes are usually not that painful (-0.0 == +0.0 for the primitive types double and float but not for their object wrappers Double and Float)

    To come back to your question, using Double as a key in the map is a terrible idea because of rounding problems. You do not need to use Math.PI for infinity since Double.POSITIVE_INFINITY is a legitimate value. Be careful though, you don't want to have positive and negative infinity mixed up. Look at the previous questions, the trick here is to represent a line by an equation ax+by+c=0 with a,b, and c of type int.

    As a final note, I think it is important to know the limitations of the encoding you are using (overflow for int, signed zeroes, infinity, and NaN of floating point numbers, surrogate pair for UTF-16…)

     所以待重新写答案 AC 一次。

  • 相关阅读:
    Boot.ini
    CCP4 SET
    Install GTK+ GLIB
    C head file
    Changes in Python
    ubuntu
    错误: 配置节中设置 validateRequest=false 可以禁用请求验证
    c++中冒号(:)和双冒号(::)的用法
    C++学习之类和结构体
    C++中双冒号的作用
  • 原文地址:https://www.cnblogs.com/liyangguang1988/p/3902258.html
Copyright © 2020-2023  润新知