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

JavaScriptでマトリックス(行列)内のラッキーナンバーを見つける方法

すべての要素が互いに異なる m × n 行列が与えられたとき、その中にある「ラッキーナンバー」をすべて見つけて返すのが今回の課題です。

ラッキーナンバーとは、自分の属する行の中で最小値であり、かつ自分の属する列の中で最大値である要素のことを指します。

具体例

たとえば、次のような入力配列を考えてみましょう。

const arr = [
    [3,7,8],
    [9,11,13],
    [15,16,17]
];

この場合の出力は次のようになります。

const output = [15];

これは、15 が最下行の中で最小の値であり、同時に第1列の中で最大の値でもあるため、この行列における唯一のラッキーナンバーだからです。

解法のコード

const arr = [
    [3,7,8],
    [9,11,13],
    [15,16,17]
];
const luckyNumbers = (arr, res = []) => {
    const M = arr.length, N = arr[0].length;
    // 各行の最小値を保持する配列
    const min = Array(M).fill(Infinity);
    // 各列の最大値を保持する配列
    const max = Array(N).fill(-Infinity);
    // 全要素を一度だけ走査して最小値・最大値を更新
    for (let i = 0; i < M; ++i)
        for (let j = 0; j < N; ++j)
            min[i] = Math.min(min[i], arr[i][j]),
            max[j] = Math.max(max[j], arr[i][j]);
    // 行の最小値と列の最大値が一致する要素を収集
    for (let i = 0; i < M; ++i)
        for (let j = 0; j < N; ++j)
            if (min[i] === max[j])
                res.push(arr[i][j]);
    return res;
};
console.log(luckyNumbers(arr));

コードのポイント

このアルゴリズムの肝は、行列全体をあらかじめ走査しておき、各行の最小値を格納した配列 min と、各列の最大値を格納した配列 max を作成することです。

その後にもう一度行列を走査し、min[i]max[j] が一致する位置 (i, j) の要素こそが、「行内で最小・列内で最大」という条件を満たすラッキーナンバーとなります。

なお、すべての数値が互いに異なるという前提があるため、ラッキーナンバーは高々1個しか存在しないという性質もあります。

計算量

  • 時間計算量:O(M × N) — 行列の全要素を最大2回走査するため
  • 空間計算量:O(M + N) — 行ごとの最小値と列ごとの最大値を保存するため

出力結果

コンソールに出力される結果は以下のとおりです。

[15]
  1. JavaScriptの数値(Number)の基本と実践サンプルコード

    JavaScriptでは、整数も小数もすべて「Number」型として扱われます。この記事では、数値変数の定義方法と、それらを使った簡単な演算の例を、動作するHTMLサンプルコードとともに紹介します。サンプルコード以下は、JavaScriptで数値を扱う基本的な例です。整数(22、99)と小数(1.523)を変数に格納し、ボタンをクリックすると画面に表示する仕組みになっています。<!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport co

  2. JavaScriptのconstとletの違いを徹底解説!ブロックスコープ変数の基本と使い方

    JavaScriptにおけるconstとletの基本const と let は、ES2015(ES6)で導入された変数宣言用のキーワードです。どちらもブロックスコープ(波括弧 { } で囲まれた範囲)に対応しているのが特徴で、関数スコープしか持たなかった従来の var とは異なる挙動を示します。両者の大きな違いは再代入の可否です。letで宣言した変数は後から何度でも値を再代入できますが、constで宣言した変数は再代入しようとするとエラー(TypeError)が発生します。letとconstの主な違い項目letconst再代入可能不可(エラー発生)スコープブロックスコープブロックスコープ宣言時