これがO(numCols*numLines^2)
アルゴリズムです。させてS[i][j] = sum of the first i elements of column j.
この例でアルゴリズムを実行します。
M
1 1 0 0 1 0
0 1 1 1 0 1
1 1 1 1 0 0
0 0 1 1 0 0
我々は持っています:
S
1 1 0 0 1 0
1 2 1 1 1 1
2 3 2 2 1 1
2 3 3 3 1 1
ここで、1 次元配列内のすべての 1 の最大部分配列を見つける問題を考えてみましょう。これは、次の単純なアルゴリズムを使用して解決できます。
append 0 to the end of your array
max = 0, temp = 0
for i = 1 to array.size do
if array[i] = 1 then
++temp
else
if temp > max then
max = temp
temp = 0
たとえば、次の 1 次元配列がある場合:
1 2 3 4 5 6
1 1 0 1 1 1
あなたはこれをします:
最初に a を追加します0
:
1 2 3 4 5 6 7
1 1 0 1 1 1 0
ここで、 を押すたびに0
、連続する一連のものがどこで終了するかがわかります。したがって、temp
現在の 1 の数の現在の合計 (変数) を保持している場合は、その合計をそれまでの最大値 (変数) と比較してmax
、ゼロに達したときに現在の合計をリセットできます。これにより、変数内の連続する 1 のシーケンスの最大長が得られますmax
。
このサブアルゴリズムを使用して、問題の解決策を見つけることができます。まず、0
行列に列を追加します。次に、 を計算しS
ます。
それで:
max = 0
for i = 1 to M.numLines do
for j = i to M.numLines do
temp = 0
for k = 1 to M.numCols do
if S[j][k] - S[i-1][k] = j - i + 1 then
temp += j - i + 1
else
if temp > max then
max = temp
temp = 0
基本的に、部分配列の可能な高さ (可能な高さがありO(numLines^2)
ます) ごとに、1 次元配列のアルゴリズムを適用して、その高さを持つ最大面積を持つものを見つけます ( O(numCols)
)。
次の「図」を考えてみましょう。
M
1 1 0 0 1 0 0
i 0 1 1 1 0 1 0
j 1 1 1 1 0 0 0
0 0 1 1 0 0 0
これは、高さがj - i + 1
固定されていることを意味します。i
ここで、その中間にある行列のすべての要素を取得しますj
。
0 1 1 1 0 1 0
1 1 1 1 0 0 0
これは 1 次元の問題に似ていることに注意してください。列を合計して、結果を見てみましょう。
1 2 2 2 0 1 0
ここで、問題は 1 次元のケースに縮小されますが、連続するj - i + 1
(2
この場合は) 値のサブシーケンスを見つけなければならないという例外があります。これは、j - i + 1
「ウィンドウ」の各列が 1 でいっぱいでなければならないことを意味します。S
これは、マトリックスを使用して効率的に確認できます。
どのように機能するかを理解するためS
に、再び 1 次元のケースを考えてみましょう: let s[i] = sum of the first i elements of the vector a
。では、部分列の合計はa[i..j]
いくつですか? これは、 までのすべての要素の合計から までのすべての要素a[j]
の合計を引いたものでありa[i-1]
、意味はs[j] - s[i-1]
です。2 番目のケースは、s
for each 列があることを除いて、同じように機能します。
ご不明な点がございましたら、お気軽にお問い合わせください。
これがあなたのニーズに合っているかどうかはわかりませんが、O(numLines*numCols)
動的計画法に基づくアルゴリズムもあると思います。あなたが求めている部分配列が正方形の場合を除いて、私はまだそれを理解できません。ただし、誰かがより良い洞察を持っているかもしれないので、もう少し待ってください.