1. 程式人生 > >LeetCode939

LeetCode939

問題:最小面積矩形

給定在 xy 平面上的一組點,確定由這些點組成的矩形的最小面積,其中矩形的邊平行於 x 軸和 y 軸。

如果沒有任何矩形,就返回 0。

 

示例 1:

輸入:[[1,1],[1,3],[3,1],[3,3],[2,2]]
輸出:4

示例 2:

輸入:[[1,1],[1,3],[3,1],[3,3],[4,1],[4,3]]
輸出:2

 

提示:

  1. 1 <= points.length <= 500
  2. 0 <= points[i][0] <= 40000
  3. 0 <= points[i][1] <= 40000
  4. 所有的點都是不同的。

連結:https://leetcode-cn.com/contest/weekly-contest-110/problems/minimum-area-rectangle/

分析:

1.四個點構成一個矩形,其中左下座標(x1,y1),右上座標(x2,y2),則另外兩個座標為(x1,y2) (x2,y1)

2.可以逐一遍歷所有點,得到以該點為左下角的最小面積,其其中的最小者。

3.獲取以某個點為左下角的所有矩形最小面積時候,對於該點(x1,y1),先得到所有的(x1,ym)和(xn,y1),檢視(xn,ym)是否在給出的點中,如果是則可以構成矩形,否則不可以,如果構成矩形,面積為(xn-x1)*(ym-y1)

4.對所有的(X1,y)和(x,Y1)排序後,假設選擇了(x1,yi)和(xn,y1)兩個點且(xn,yi)在給出的點中那麼對於後續的(x1,yi+1)和(xn,y1)都不用看了,即使構成了矩形面積也大於(x1,yi),而且對於後續的(x1,yi+1)進行嘗試的時候,只需要檢視{(xm,y1),m<n}面積是否更小即可。

如圖中所示,最小面積只能在(xi,yi)和(xi-,yi+)之中選擇較小者。【對於固定的Xi,如果Yi能構成面積,Yi+即使能夠成,得到的面積也會更大,而對於Yi+,如果X>Xi,則(X ,Yi)的面積必定大於(Xi,Yi)】

AC Code:

 

class Solution
{
public:
	int minAreaRect(vector<vector<int>>& points)
	{
		int ret = INT_MAX;
		sort(points.begin(), points.end());
		for (int i = 0; i < points.size(); i++)
		{			
			vector<vector<int> > getxs;
			vector<vector<int> > getys;
			//得到X值相同的點
			getxs = GetXs(points, i+1, points[i]);
			//得到Y值相同的點
			getys = GetYs(points, i + 1, points[i]);
			if (getxs.size() == 0 || getys.size() == 0)
			{
				continue;
			}
			int tmparea = GetMiniRect(points, getxs, getys, points[i]);
			if (ret > tmparea)
			{
				ret = tmparea;
			}

		}
		if (ret == INT_MAX)
		{
			ret = 0;
		}
		return ret;
	}
	int GetMiniRect(vector<vector<int> > points, vector<vector<int> > Xs, vector<vector<int> > Ys, vector<int> startpoint)
	{
		int ret = INT_MAX;
		vector<int> tmpx;
		vector<int> tmpy;
		//一條水平線上的,按照y排序
		//sort(Xs.begin(), Xs.end(), cmpY);
		//一條豎直線上的,按照x排序
		//sort(Ys.begin(), Ys.end(), cmpX);

		int x1, y1, x2, y2;
		x1 = startpoint[0];
		y1 = startpoint[1];
		
		int jend = Ys.size();
		for (int i = 0; i < Xs.size(); i++)
		{
			y2 = Xs[i][1];
			for (int j = 0; j < Ys.size() && j<jend; j++)
			{
				x2 = Ys[j][0];
				vector<int> tmp = vector < int > {x2, y2};
				if (std::find(points.begin(), points.end(), tmp) != points.end())
				{					
					int local = (x2 - x1)*(y2 - y1);	
					if (ret > local)
					{
						ret = local;
					}
					jend = j;
					break;
				}
				else
				{
					continue;
				}
			}
		}
		
		return ret;
	}
	vector<vector<int> > GetXs(vector<vector<int> > points, int begin, vector<int> target)
	{
		vector<vector<int> > ret;
		for (int i = begin; i < points.size(); i++)
		{
			if (points[i] == target)
			{
				continue;
			}
			if (points[i][0] == target[0] && points[i][1] > target[1])
			{
				ret.emplace_back(points[i]);
			}
		}
		return ret;
	}
	vector<vector<int> > GetYs(vector<vector<int> > points, int begin, vector<int> target)
	{
		vector<vector<int> > ret;
		for (int i = begin; i < points.size(); i++)
		{
			if (points[i] == target)
			{
				continue;
			}
			if (points[i][1] == target[1] && points[i][0] > target[0])
			{
				ret.emplace_back(points[i]);
			}
		}
		return ret;
	}

};

  

其他:

1.對於多重vector,比如vector<vector<int> >執行sort函式後,會自動對所有元素都進行排序,即每個vector內部也會排序,做題的時候不確定這個,還特意編寫自定義排序。

2.最開始考慮到(1X5 5X1 2X2)面積中2X2最小,做的是雙重迴圈O(n*n)超時,考慮到沿著Y軸進行嘗試,一旦得到一個矩形,X的上限就確定了,資料量大大減少

3.過程中遇到本地執行除錯都對,提交提示記憶體地址對齊錯誤,最終發現是由於數字訪問越界,而定位問題的方法則是提交試錯:通過刪減程式碼,定位到當有x2 = Ys[i][0];語句存在時候提交就會報這樣的錯誤,實際上應該是x2 = Ys[j][0];。