Hash table and record of line points -- Calculation of the maximum number of points on the line

Posted by hame22 on Mon, 24 Jan 2022 18:07:23 +0100

subject


oj platform

Topic analysis

  • There are two ways to solve this problem, but without exception, hash tables are needed.
  1. The first solution is to record the slope and intercept of the line.
    Specific steps:
  • Write a function for calculating the slope and intercept between any two points, and the return value is a binary.
  • Enumerate the slope and intercept of any two points. When they are the same, they are regarded as points on the same straight line. Take the slope and intercept as the key and the point number as value, and record them through the hash table. If the key is the same, you need to judge whether the point has appeared. If it does, you don't need to record the point (just use set)
  • Update the maximum number of points corresponding to key, that is, the maximum number of points on the line.
  1. The second solution: by recording the slope of the line.
    Specific method (according to the methodology, the basic steps can be formed):
  • Since only the slope is used to judge whether it is the same straight line, it is obvious that there may be coincidence. How to solve this situation? We can solve this problem in the process of enumeration. We only need to enumerate all situations of a point in each round (take any other point to update the slope), and each round of situations are solved with a separate hash table (very important), that is, when enumerating at another point, re record each slope, so there will be no repeated calculation.

How to calculate the slope? This is actually a knowledge. We can use division to get decimal calculation, but in fact, there will be a certain loss of accuracy. The best way is to use a binary, but we need to convert the binary into the simplest fractional form!

  • How to simplify the fractional binary?
    We can divide the numerator and denominator by the greatest common factor at the same time to achieve the simplest fractional form.

gcd function (rolling Division) implementation:

int gcd(int a,int b){
	return b ? gcd(b,a%b) : a;
}

The first solution

Average efficiency:

class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int size = points.size();
        if(size==1)
            return 1;
        //Selection of any two points
        int res = 0;
        for(int i=0;i<size;i++){
            for(int j=i+1;j<size;j++){
            //rvalue reference 
                pair<double,double>&& t =  solve(points[i],points[j]);
                auto q = times.find(t);
                if(q!=times.end()){
                //lvalue reference 
                    set<int>&s = q->second;
                    s.insert(i);
                    s.insert(j);
                    int x = s.size();
                    res = max(res,x);
                }else{
                     set<int>&s = times[t];
                    s.insert(i);
                    s.insert(j);
                    int x = s.size();
                    res = max(res,x);
                }
        }
    }
    return res;
}
private:
//The hash table is used to record the number of points on the same line
map<pair<double,double>,set<int>>times;
//Used to return k,b to identify whether it is the same line
    pair<double,double> solve(vector<int>& point1,vector<int>& point2){
        if(point1[0]==point2[0])return {INT_MAX,point1[0]};
        double k = (double)(point1[1]-point2[1])/(point1[0]-point2[0]);
        double b = -k*point1[0]+point1[1];
        return {k,b};
    }
};

The second solution

Efficiency yyds

class Solution {
public:
    int gcd(int a, int b) {
        return b ? gcd(b, a % b) : a;
    }

    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if (n <= 2) {
            return n;
        }
        int ret = 0;
        for (int i = 0; i < n; i++) {
            //For each round of enumeration, a different hash table is established, and the maximum result is directly updated at the end
            unordered_map<int, int> mp;
            for (int j = i + 1; j < n; j++) {
                int x = points[i][0] - points[j][0];
                int y = points[i][1] - points[j][1];
                //For special cases, the fractional binary is specially treated
                if (x == 0) {
                    y = 1;
                } else if (y == 0) {
                    x = 1;
                } else {
                    //Unify the positive and negative of two tuples
                    if (y < 0) {
                        x = -x;
                        y = -y;
                    }
                    //Simplified binary
                    int&& gcdXY = gcd(abs(x), abs(y));
                    x /= gcdXY, y /= gcdXY;
                }
                //Update the current mp
                mp[y + x * 20001]++;
            }
//Updates the maximum value based on the answers currently mp recorded. (note that since the mp median records how many points have the same slope as this point, it also needs + 1 to include itself)
            for (auto& [_, num] : mp) {
                ret = max(ret, num + 1);
            }
        }
        return ret;
    }
};

Topics: Algorithm data structure Hash table