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

Pythonで配列を互いに素な左右の部分配列に分割する方法を解説

問題の概要

配列 nums が与えられたとき、これを「left」と「right」という2つの部分配列に分割します。この分割は、以下の条件を満たす必要があります。

  • left 内のすべての要素が、right 内のどの要素以下であること
  • left と right がどちらも空でないこと
  • left のサイズが可能な限り小さいこと

そして、このような分割を行った後の left の長さを求めます。

具体例

たとえば、入力が nums = [5,0,3,8,6] の場合、出力は 3 になります。これは、left 配列が [5,0,3]、right 部分配列が [8,6] に分割されるためです。

解法のアプローチ

この問題は、配列を一度だけ走査しながら最大値を追跡することで、O(n) の計算量で効率的に解けます。以下の変数を使用します。

  • mx: 現在の left 部分配列の最大値(初期値は null)
  • nmx: 直近までに現れた要素の最大値(将来の候補)
  • temp: 分割境界のインデックス
  • temp2: 現在走査中の位置を表すカウンター

各要素に対して、以下のように処理を進めます。

  • mx が未設定(null)の場合:最初の要素なので、mxnmx をその要素で初期化し、temp を現在位置に設定します。
  • i >= mx の場合:この要素は left に入れても条件を壊さないため、そのまま進みます。必要に応じて nmx を更新します。
  • i < mx の場合:left の最大値より小さい要素が出現したため、分割点をここまで延ばす必要があります。temp を現在位置に更新し、mxnmx(直近までの最大値)に置き換えます。

最後に temp + 1 を返すことで、left の長さが求まります。

Pythonでの実装例

それでは、実際のコードを見てみましょう。

def solve(nums):
    mx = None
    temp = None
    nmx = None
    temp2 = 0

    for i in nums:
        if mx is None:
            mx = i
            nmx = i
            temp = temp2
            temp2 += 1
            continue

        if i >= mx:
            temp2 += 1
            if i > nmx:
                nmx = i
            continue
        else:
            temp = temp2
            temp2 += 1
            mx = nmx
            continue

    return temp + 1

nums = [5,0,3,8,6]
print(solve(nums))

入力

[5,0,3,8,6]

出力

3

計算量について

このアルゴリズムの計算量は以下の通りです。

  • 時間計算量: O(n) — 配列を一度だけ走査すればよいため、非常に高速です。
  • 空間計算量: O(1) — 追加のデータ構造が不要で、メモリ使用量は一定です。

最大値の追跡というシンプルな発想で、配列の分割問題を線形時間で解決できる点が、この手法の大きな魅力です。

  1. Pythonで配列内の最大要素を見つける方法【初心者向け解説】

    本記事では、配列の中から最大の要素を見つけるための解法とアプローチについて詳しく解説します。 問題の概要 配列が入力として与えられたとき、その中から最も大きい要素を見つけ出すことが課題となります。 アプローチ この問題は「線形探索」と呼ばれるシンプルな手法で解決できます。手順は以下の通りです。 まず、変数 max を配列の最初の要素で初期化します。 次に、2番目の要素から配列の末尾まで順番に走査していきます。 走査中の各要素について、現在の max の値と比較します。 要素が max より大きければ、max の値をその要素で更新します。 そうでなければ、そのまま次の要素へ進みます。 この処

  2. 【Python】配列の全要素の積をnで割った余りを求めるプログラムの書き方

    本記事では、以下の問題に対する解決策について詳しく解説します。問題文複数の数値からなる配列と整数 n が与えられたとき、配列内のすべての要素を掛け合わせた結果を n で割った余りを出力する必要があります。アプローチまず、arr[i] % n のように各要素の余りを個別に計算します。次に、その余りを現在の結果に掛け合わせます。掛け算を行うたびに再度剰余演算を適用することで、オーバーフローを回避できます。この手法は、モジュラー算術(合同式)の分配則に基づいています。( a * b) % c = ( ( a % c ) * ( b % c ) ) % c実装例def findremainder(ar