JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

【JavaScript】行列の中で最も長い連続する1のラインを見つける方法

問題の概要

本記事では、0と1のみで構成された2次元配列(バイナリ行列)の中から、最も長く連続する「1」のラインを見つけるJavaScript関数の実装方法を解説します。まず、次のようなバイナリ行列を例に考えてみましょう。

const arr = [
   [0,1,1,0],
   [0,1,1,0],
   [0,0,0,1]
];

作成する関数は、このような行列を第一引数(唯一の引数)として受け取ります。そして、水平・垂直・斜め・逆斜めのいずれかの方向に並んだ連続する「1」の最長ラインを検索し、そのラインに含まれる1の個数を返します。

上記の行列の場合、期待される出力は次の通りです。

const output = 3

これは、arr[0][1] の位置から始まる斜め方向のラインが、arr[2][3] まで3つ連続しており、これが最長となるためです。

アルゴリズムの考え方:動的計画法(DP)

この問題は、動的計画法(Dynamic Programming)を用いることで効率的に解くことができます。基本的なアプローチは以下の通りです。

  • 各セルに対して、4つの方向(水平・垂直・斜め・逆斜め)それぞれについて「そのセルまでの連続する1の長さ」を記録するDPテーブルを作成します。
  • セルの値が1である場合、進行方向にある直前のセルのDP値を参照し、長さを更新します。
  • 処理の過程で全体の最大値を追跡し、最終的にその値を返します。

実装コード

実際のコードは以下のようになります。

const arr = [
   [0,1,1,0],
   [0,1,1,0],
   [0,0,0,1]
];
const longestLine = (arr = []) => {
   if(!arr.length){
      return 0;
   }
   let rows = arr.length, cols = arr[0].length;
   let res = 0;
   const dp = Array(rows).fill([]);
   dp.forEach((el, ind) => {
      dp[ind] = Array(cols).fill([]);
      dp[ind].forEach((undefined, subInd) => {
         dp[ind][subInd] = Array(4).fill(null);
      });
   });
   for (let i = 0; i < rows; i++) {
      for (let j = 0; j < cols; j++) {
         if (arr[i][j] == 1) {
            dp[i][j][0] = j > 0 ? dp[i][j - 1][0] + 1 : 1;
            dp[i][j][1] = i > 0 ? dp[i - 1][j][1] + 1 : 1;
            dp[i][j][2] = (i > 0 && j > 0) ? dp[i - 1][j - 1][2] + 1 : 1;
            dp[i][j][3] = (i > 0 && j < cols - 1) ? dp[i - 1][j + 1][3] + 1 : 1;
            res = Math.max(res, Math.max(dp[i][j][0], dp[i][j][1]));
            res = Math.max(res, Math.max(dp[i][j][2], dp[i][j][3]));
         };
      };
   };
   return res;
};
console.log(longestLine(arr));

コードのポイント

  • DPテーブルの構造: dp[i][j] は4つの要素を持つ配列で、それぞれ「水平」「垂直」「斜め」「逆斜め」方向における連続する1の長さを格納します。
  • 境界チェック: 各方向について行・列の端に達していないかを三項演算子で判定し、端であれば長さを1から再カウントします。
  • 計算量: 行列の全セルを一度だけ走査するため、時間計算量は O(rows × cols) となり、大規模な行列でも高速に動作します。

出力結果

このコードを実行すると、コンソールには以下の出力が表示されます。

3

これは、arr[0][1] から arr[2][3] へと斜め方向に続く3つの1が、行列内で最長のラインであることを示しています。

  1. JavaScriptで最長のペアチェーンを見つける方法

    問題数値ペア(組)の配列 arr を唯一の引数として受け取り、形成可能な最長チェーンの長さを返す JavaScript 関数を作成します。各ペアにおいて、最初の数値は必ず 2 番目の数値より小さいものとします。ここで、ペア (c, d) が別のペア (a, b) の後に続けられるのは、b < c が成り立つ場合に限られると定義します。このルールに従ってペアの連鎖(チェーン)を形成することができ、本関数はその中で最も長いチェーンの長さを求める必要があります。入力例const arr = [     [1, 2], [2, 3], [3, 4] ];出

  2. C++でマトリックス内の連続する1の最長ラインを求める方法(動的計画法)

    問題概要 0と1だけで構成されたバイナリ行列 M が与えられます。この行列の中から、連続した1が並ぶ最長のラインの長さを求めてください。ラインの向きは、水平方向・垂直方向・斜め(対角線)方向・反斜め(逆対角線)方向のいずれかです。 例として、次のような入力を考えてみましょう。 011001100001 この場合の出力は 3 です。(0,1) → (1,2) → (2,3) と、左上から右下へ向かう対角線上に1が3つ連続して並んでいるためです。 解法アプローチ:動的計画法(DP) この問題は、4つの方向それぞれについて「そのセルを終点とする連続する1の長さ」を記録する動的計画法で効率的に解くこ