C++で2値行列に4つのコーナーがすべて1の長方形が存在するかを判定する方法
問題の概要
0と1のみで構成される2値行列が与えられたとします。この行列の中に、4つのコーナー(角)がすべて1である長方形が存在するかどうかを判定するのが、本記事のテーマです。
例として、次のような行列を考えてみましょう。
| 1 | 0 | 0 | 1 | 0 |
| 0 | 0 | 1 | 0 | 1 |
| 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
この行列の場合、答えは「はい」となります。実際に、コーナーがすべて1である長方形が存在します。
| 1 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 0 | 1 |
上の部分行列に注目すると、左上・右上・左下・右下の4つのコーナーがすべて1になっていることが確認できます。
解決のためのアプローチ
この問題を効率的に解くために、ハッシュセット(unordered_set)を活用した手法を採用します。アルゴリズムの流れは以下のとおりです。
行列を上から下へ、一行ずつ走査します。
各行において、値が1となる2つの列(j と k)の組み合わせをすべて調べ、そのペアをハッシュマップに記録します。
それ以降の行で同じ列のペア(j と k が再び両方とも1)が見つかった場合、その4つの要素が長方形の4つのコーナーを形成していることになります。
同じ列ペアが2回以上出現した時点で長方形の存在が確定するため、無駄な探索を省き、効率的に判定できます。
C++による実装例
#include<iostream>
#include<unordered_set>
#include<unordered_map>
#include<vector>
using namespace std;
bool isRectanglePresent(const vector<vector<int> >& matrix) {
int rows = matrix.size();
if (rows == 0)
return false;
int columns = matrix[0].size();
unordered_map<int, unordered_set<int> > table;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns - 1; ++j) {
for (int k = j + 1; k < columns; ++k) {
if (matrix[i][j] == 1 && matrix[i][k] == 1) {
if (table.find(j) != table.end() && table[j].find(k) != table[j].end())
return true;
if (table.find(k) != table.end() && table[k].find(j) != table[k].end())
return true;
table[j].insert(k);
table[k].insert(j);
}
}
}
}
return false;
}
int main() {
vector<vector<int> > matrix = {
{ 1, 0, 0, 1, 0 },
{ 0, 0, 1, 0, 1 },
{ 0, 0, 0, 1, 0 },
{ 1, 0, 1, 0, 1 }
};
if (isRectanglePresent(matrix))
cout << "Rectangle is present";
else
cout << "Rectangle is not present";
}出力
Rectangle is present
計算量の目安
このアルゴリズムの時間計算量は O(行数 × 列数²) となります。これは、各行についてすべての列ペアを調べるためです。また、空間計算量は O(列数²) となり、記録する列ペアの数に依存します。行列のサイズが大きい場合でも、ハッシュを利用した高速な検索により、実用的な速度で動作します。
-
C++で二分木の葉ノードを繰り返し収集・削除するアルゴリズム
問題の概要 二分木が与えられているとします。まずすべての葉(子ノードを持たないノード)を収集して取り除き、その操作を木が空になるまで繰り返します。 例えば、次のような二分木が入力として与えられた場合を考えてみます。 このとき、出力は [[4,5,3],[2],[1]] となります。最初のラウンドで葉である 4、5、3 が取り除かれ、続いて 2 が、最後に根の 1 が残るという流れです。 解法のアプローチ この問題は、各ノードの「高さ」(最も深い葉から数えた距離)をDFSで求めると効率的に解けます。同じ高さを持つノードは、必ず同じラウンドで葉になるためです。具体的な手順は以下の通りです。
-
C++で中点の座標を使って長方形の4つの頂点を求める方法
問題の概要長方形 ABCD があり、その中点 P と Q の座標、および長方形の辺の長さ L のみが分かっているとします。この課題の目的は、P と Q の座標および辺の長さ L を使って、頂点 A、B、C、D の座標を求めることです。例えば、P が (1, 0)、Q が (1, 2)、L が 2 の場合、A、B、C、D はそれぞれ (0, 0)、(0, 2)、(2, 2)、(2, 0) となります。考えられる3つの場合P と Q の位置関係によって、次の3つの場合が考えられます。長方形が水平な場合:AD と BC が X 軸に平行長方形が垂直な場合:AD と BC が Y 軸に平行長方形が軸に