演算法設計與分析第二週作業leetcode
阿新 • • 發佈:2018-12-10
題目需要求出在同一條直線的最大點數。 咋一看比較簡單,於是就直接拿斜率來求解,斜率一樣的也就是在一條直線上。 但很快開始暴露出問題,
- 一是可能有不同的點位置重合
- 二是斜率的精度應該要用何種方法儲存,因為如果用浮點數儲存,那麼會有精度問題,特別是當點的橫座標和縱座標比較大的時候,會出現精度誤差,從而影響運算結果。
- 第三點需要考慮的是資料儲存結構,例如我一開始用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;
}
};