有乙個n * n
的矩形,其中每個元素只可能是0
or1
。比如如下矩陣a:
1 1 0 0
0 0 1 1
1 0 1 0
1 1 0 1
其中a[0][0], a[0][1], a[3][0], a[3][1]
這四個元素恰好是乙個長方形的四個角,且每個元素都是1. 因此稱這四個元素圍成了乙個子矩形。
現在需要判斷,給定的矩陣a中,判斷是否存在這樣四個元素,都是1,且恰好圍成乙個子矩形?
暴力法顯然,只需要列舉 top-left,還有 bottom-right 就可以確定出這四個元素了。top-left [i1, j1], bottom-right [i2, j2]。偽**如下:
for
i1<- 0 to
n-1for
j1<- 0 to
n-1for
i2<-
i1 + 1 to
n-1for
j2<-
j2 + 1 to
n-1check_are_all_one(a
[i1]
[j1], a
[i1]
[j2], a
[i2]
[j1], a
[i2]
[j2])
t(n) = o(n^4)
改進方案1
可以只需要列舉j1, j2
, 然後 i 從 0 ~ n-1 掃瞄一遍就行。
for j1 <-0to
n-1for
j2<-
j1+1
ton-1
one_pair_count
<-
0for
i<-0to
n-1if
a[i][j1] & a[i][j2] then
one_pair_count
<-
one_pair_count + 1
ifone_pair_count >
= 2 then // 只需要出現過兩次a[i][j1], a[i][j2]都是1,就可以由他們圍成乙個矩形
return true
return false
時間複雜度為 t(n) = o(n^3)
改進方案2
這個方案可以將複雜度改進為 o(n^2),但是需要引入輔助空間,mark[n][n]
a矩陣:
1 1 0 0
0 0 1 1
1 0 1 0
1 1 0 1
從a的第一行開始往下掃,
row 1:1 1 0 0
這裡意味著第一列(column 1,簡稱c1) 和第二列(column 2,簡稱c2)可以構成乙個待求矩形的上邊。對應的mark表為:
c1 c2 c3 c4
c1 0 1 0 0
c2 1 0 0 0
c3 0 0 0 0
c4 0 0 0 0
如果row1 是:1 1 0 1
,那麼意味著 c1 和 c2,c2 和 c3,c1 和 c3都可以構成矩形的上邊。此時對應的mark表為:
c1 c2 c3 c4
c1 0 1 0 1
c2 1 0 0 1
c3 0 0 0 0
c4 1 1 0 0
掃瞄第二行,row2:0 0 1 1
,c3, c4為1,更新mark[3-1][4-1]=1, mark[4-1][3-1]=1
mark表更新為:
c1 c2 c3 c4
c1 0 1 0 0
c2 1 0 0 0
c3 0 0 0 1
c4 0 0 1 0
掃瞄第三行:row3:1 0 1 0
, c1,c3為1,更新mark[1-1][3-1]=1, mark[3-1][1-1]=1
mark表更新為:
c1 c2 c3 c4
c1 0 1 1 0
c2 1 0 0 0
c3 1 0 0 1
c4 0 0 1 0
掃瞄第四行,row4:1 1 0 1
,c1,c2,c4為1,更新mark[1-1][2-1]=1, mark[2-1][1-1]=1, mark[1-1][4-1]=1, mark[4-1][1-1]=1, mark[2-1][4-1]=1, mark[4-1][2-1]=1
mark表更新為
c1 c2 c3 c4
c1 0 2 0 1
c2 2 0 0 1
c3 0 0 0 0
c4 1 1 0 0
此時發現mark[0][1] = 2
,即意味著第一列和第二列有兩次掃瞄中,都匹配上了,這樣的話,選擇第一列和第二列作為矩形的左右列即可,然後從上往下掃一次(o(n)時間),即可求得矩形上下邊界
總的時間複雜度分析:
**如下:
#include
#include
#include
#include
using
namespace
std;
class solution ,,,
};vector
> matrix;
for (int i = 0; i < 4; i++)
cout
<< "check: "
<< checkhasrectangle(matrix) << endl;
}bool checkhasrectangle(vector
> &matrix)
}// cout
printf("four elements: (%d,%d), (%d,%d), (%d,%d), (%d,%d)\n",
target_r1, target_c1, target_r1, target_c2,
target_r2, target_c1, target_r2, target_c2);
return
true;}}
}}
return
false;
}};int main()
LA3029 矩陣中求子矩陣最大問題
la3029 題意給你乙個矩陣,每個單元格要麼為空,要麼為滿,求全是空的最大子矩陣的格仔數 3.最樸素的演算法是列舉所有的子矩陣的左上角的點和右下角的點,這樣就能確定乙個矩形,然後再遍歷這個矩陣,看矩陣是否全是空。複雜度大概是o m 2 n 2 通過掃瞄法,每次維護left i j right i ...
CDQ求子矩陣的和
description 維護乙個w w的矩陣,初始值均為s.每次操作可以增加某格仔的權值,或詢問某子矩陣的總權值.修改運算元m 160000,詢問數q 10000,w 2000000.input 第一行兩個整數,s,w 其中s為矩陣初始值 w為矩陣大小 接下來每行為一下三種輸入之一 不包含引號 1 ...
OfferX 矩形和矩陣
題目 48.rotate image 將乙個矩形順時針翻轉90 解 先將矩形按行翻轉,然後進行mirror操作 class solution public void reverse int matrix public void mirrorrotate int matrix public void ...