1. 程式人生 > >演算法設計與分析第二週作業leetcode

演算法設計與分析第二週作業leetcode

題目需要求出在同一條直線的最大點數。 咋一看比較簡單,於是就直接拿斜率來求解,斜率一樣的也就是在一條直線上。 但很快開始暴露出問題,

  • 一是可能有不同的點位置重合
  • 二是斜率的精度應該要用何種方法儲存,因為如果用浮點數儲存,那麼會有精度問題,特別是當點的橫座標和縱座標比較大的時候,會出現精度誤差,從而影響運算結果。
  • 第三點需要考慮的是資料儲存結構,例如我一開始用struct+vector的方式儲存,但在查詢相同斜率的點時需要o(n)的複雜度,明顯不如map的直接對映效率高。
//原來的資料結構
struct Slope {
    float slope;
    int times;
    Slope(float
s,int t) :slope(s), times(t) {} };

因此針對上面的三點,分別作出的該進如下:

  • 將重合的點用map< pair< int, int>, int> pointsMap來去重
  • 對於斜率精度問題,用string來儲存被除數和除數,在儲存之前先同時除以最大公約數化簡。
  • 對於資料儲存結構,利用map < string, int > 的結構代替struct slope+ vector < slope >
//原來的程式碼
class Solution {
    struct Slope {
        float
slope; int times; Slope(float s,int t) :slope(s), times(t) {} }; float slopeTemp; vector<Slope> SlopeVec; int samepoint; bool isPush; public: int maxPoints(vector<Point>& points) {//還有[] 的輸入 Slope ss(LONG_MAX,0);//用來儲存橫座標相等的 SlopeVec.push_back(ss); if
(points.size() == 0) { return 0; } for (int i = 0; i < points.size(); i++) { samepoint = 0; for (int j = i+1; j < points.size(); j++) { isPush = false; if (points[i].x == points[j].x &&points[i].y == points[j].y) { samepoint++; } else if (points[i].x == points[j].x) { SlopeVec[0].times++; break; } slopeTemp = (float)(points[i].y - points[j].y) / (float)(points[i].x - points[j].x); for (int x = 1; x < SlopeVec.size(); x++) {//第零位用來存橫座標相等的 if ( fabs(slopeTemp-SlopeVec[x].slope)<1e-6 ) { SlopeVec[x].times++; isPush = true; } } if (!isPush) { Slope slope(slopeTemp, 1); SlopeVec.push_back(slope); } } } int maxTimes = 0; for (int i = 0; i < SlopeVec.size(); i++) { if (SlopeVec[i].times > maxTimes) { maxTimes = SlopeVec[i].times; } } int result = 1; while (maxTimes != 1) { maxTimes = maxTimes - result; result++; } return result; } };

下面是最終的通過程式碼,但效率還不夠高,但理解較方便,先用map去重,再用記錄斜率的map來儲存同個斜率上的點數。

class Solution {
    map<pair<int, int>, int> pointsMap;
    int samepoint;
    int sameX;
    int result, resultTemp;
    int xLength, yLength, g;
public:
    /* 迭代法(遞推法):歐幾里得演算法,計算最大公約數 */
    int gcd(int m, int n) {
        while (m>0) {
            int c = n % m;
            n = m;
            m = c;
        }
        return n;
    }
    int maxPoints(vector<Point>& points) {//還有[] 的輸入
        result = 0;
        if (points.size() == 0) {
            return 0;
        }
        for (int i = 0; i < points.size(); i++) {
            pair<int, int> pairTemp(points[i].x, points[i].y);
            pointsMap[pairTemp]++;
        }
        for (auto i = pointsMap.begin(); i != pointsMap.end(); i++) {
            sameX = 0;
            resultTemp = 0;
            map<string, int> slopeMap;
            for (auto j = i; j != pointsMap.end(); j++) {
                if (i == j) {
                    continue;
                }
                if (i->first.first == j->first.first) {//points[i].x == points[j].x
                    pair<int, int> temp(j->first.first, j->first.second);
                    sameX += pointsMap[temp];
                }
                else {
                    xLength = i->first.first - j->first.first;
                    yLength = i->first.second - j->first.second;//points[i].y - points[j].y;    
                    g = gcd(abs(xLength), abs(yLength));//第一個係數不能為0
                    xLength /= g;
                    yLength /= g;
                    if (yLength < 0) {//確保y長度為正數
                        yLength *= -1;
                        xLength *= -1;
                    }
                    stringstream ss;
                    ss << xLength << "," << yLength;
                    string slopeStr(ss.str());
                    pair<int, int> temp(j->first.first, j->first.second);
                    slopeMap[slopeStr] += pointsMap[temp];
                    resultTemp = max(resultTemp, slopeMap[slopeStr]);//找到相同斜率下最多點的那個斜率
                }
            }
            resultTemp = max(resultTemp, sameX);//找出與此點同列的點數比較
            pair<int, int> temp(i->first.first, i->first.second);
            result = max(result, resultTemp + pointsMap[temp]);
        }
        return result;
    }
};