鏈接:https://leetcode-cn.com/problems/perfect-rectangle/description/
題目
我們有 N 個與坐標軸對齊的矩形, 其中 N > 0, 判斷它們是否能精確地覆蓋一個矩形區域。
每個矩形用左下角的點和右上角的點的坐標來表示。例如, 一個單位正方形可以表示為 [1,1,2,2]。 ( 左下角的點的坐標為 (1, 1) 以及右上角的點的坐標為 (2, 2) )。



思路
首先,rectangles[][]數組里保存的每個小矩形,都有4個角.
以示例4的rectangles[0]矩形的左下角為例:
因為rectangles[0]等於{1,1,3,3},所以左下角為(1,1),處於的位置為{0,1}
所以,下面程序便通過一個 method[4][2]數組來存儲4個角度的標志位,方便調用4個角出來:
int method[4][2]={{0,1},{2,3},{0,3},{2,1}}; //左下,右上,左上,右下
由於需要多個小矩形湊成的大矩形,且不能有相交區域,所以應該共有4個獨立的角
比如示例1,就有4個獨立的角:

而示例4,有相交區域,所以不止超過4個獨立的角:

除了計算獨立的角以外,還要計算矩形是否重疊過,以及核對矩形面積.
比如下例所示,同樣,也是4個獨立的角,不僅有相交區域,而且還不是一個矩形區域:
rectangles = [ [1,1,3,2], [1,1,3,2], [1,3,3,4], ]
繪制成圖后:

所以在代碼里,需要定義2個數組
一個用來存儲角的位置,以及左下,右上,左上,右下的標志位。
另一個用來存儲矩形區域的left,low,right,top的范圍,用來核對面積用。
當我們每取出來一個角,都需要去匹配是否與以前的角重疊,為了效益需要用到Hash表,C語言沒有Hash表函數,所以我們還需要自己來編寫Hash表函數
代碼如下:
#define AREA(rectang) ((rectang[3]-rectang[1])*(rectang[2]-rectang[0])) #define Index(x,y,Hashlen) ((x*x+y*y)%Hashlen) void Hash_Init(int Hash[][8],int len) { for(int i=0;i<len;i++) { Hash[i][7]=0; } } //首先查找表,如果存在,則檢查該角度是否被重疊,如果不存在,則插入表 bool Hash_search_insert(int Hash[][8],int x,int y,int angle,int *angles,int len) { int addr=Index(x,y,len); //求哈希地址 int tmp =addr;
//查找 while(Hash[addr][7]==1) { if(Hash[addr][0]==x&&Hash[addr][1]==y) //已找到 { if(Hash[addr][angle]==0) //未重疊 { if(Hash[addr][6]==0) // 是否 合並 過 { Hash[addr][6]=1; (*angles)--; } Hash[addr][angle]=1; //設為占用 return true; } else //已重疊 return false; } addr = (addr+1)% len; if(addr==tmp) //未找到 return false; } //Hash[addr][7]等於0,說明沒找到,則插入表 Hash[addr][7]=1; Hash[addr][0]=x; Hash[addr][1]=y; Hash[addr][6]=0; //未合並過 (*angles)++; for(int i=2;i<6;i++) //左下,右上,左上,右下 if(i==angle) Hash[addr][i]=1; else Hash[addr][i]=0; return true; } bool isRectangleCover(int** rectangles, int rectanglesRowSize, int rectanglesColSize) { int i,j,k,angle=0,cnt=0; int Hashlen=rectanglesRowSize*8; int s[Hashlen][8]; // x y 左下,右上,左上,右下 是否被合並 是否被使用 int method[4][2]={{0,1},{2,3},{0,3},{2,1}}; //左下,右上,左上,右下 int Rectangles[4]={999999,999999,-999999,-9999999}; //大矩形 left,low,right,top unsigned long long Area; //大矩形面積 unsigned long long Fact_Area=0; //實際面積 int tmp[2]; //用來獲取角的位置 Hash_Init(s,Hashlen); for(i=0;i<rectanglesRowSize;i++) { Fact_Area +=AREA(rectangles[i]); for(j=0;j<4;j++) { if(j<2) //計算left,low { if(Rectangles[j]>rectangles[i][j]) Rectangles[j]=rectangles[i][j]; } else if(Rectangles[j]<rectangles[i][j]) //計算 right,top Rectangles[j]=rectangles[i][j]; tmp[0]=rectangles[i][method[j][0]]; tmp[1]=rectangles[i][method[j][1]]; if(!Hash_search_insert(s,tmp[0],tmp[1],j+2,&angle,Hashlen)) return false; } } if(angle!=4) return false; Area =AREA(Rectangles); //printf("angle%d,Fact_Area%ld,Area%ld\n",angle,Fact_Area,Area); if(Fact_Area==Area) //核對面積 return true; else
return false; }
