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

Pythonで1つのリストを別のリストへ変換するのに必要なスワップ回数をカウントするプログラム

問題の概要

2つの数値リスト L1 と L2 があるとします。各リストの長さは n で、すべての値はリスト内で一意であり、値の範囲は 0 ~ n-1 です。このとき、L1 を L2 に変換するために必要な「隣接要素のスワップ(交換)」の最小回数を求めます。

例えば、入力が L1 = [0, 1, 2, 3]、L2 = [2, 0, 1, 3] の場合、出力は 2 になります。まず 1 と 2 を入れ替えると L1 は [0, 2, 1, 3] になり、次に 0 と 2 を入れ替えると L1 は [2, 0, 1, 3] となり、L2 と一致するためです。

解決のアプローチ

この問題は、以下の手順で解くことができます。

  • 答えを格納する変数 ans を 0 で初期化します。
  • L2 の各要素 req について、次の処理を順に行います。
    • L1 内での req のインデックス i を取得します。
    • L1 から i 番目の要素を削除します。
    • ans に i を加算します。
  • 最後に ans を返します。

このアルゴリズムのポイントは、「L2 の先頭から順に要素を揃えていくとき、その要素を正しい位置まで移動させるのに必要な隣接スワップの回数は、現在の L1 内でのその要素のインデックスに等しい」という性質を利用している点です。

実装例

それでは、実際のコードを見て理解を深めましょう。

class Solution:
    def solve(self, L1, L2):
        ans = 0
        for req in L2:
            i = L1.index(req)
            L1.pop(i)
            ans += i
        return ans

ob = Solution()
L1 = [0, 1, 2, 3]
L2 = [2, 0, 1, 3]
print(ob.solve(L1, L2))

入力

[0, 1, 2, 3],[2, 0, 1, 3]

出力

2

計算量について

この実装では、index() による検索と pop() による削除がそれぞれ O(n) のコストを持つため、全体の計算量は O(n²) になります。リストのサイズが大きい場合は、Binary Indexed Tree(BIT)やマージソートを使って転倒数を求める手法を採用すると、O(n log n) まで高速化できます。

  1. Pythonで文字列の異なる部分文字列の個数を数える方法(トライ木による解法)

    文字列 s が与えられたとき、その中に含まれる「空でない異なる部分文字列」が何種類あるかを求める問題を考えてみましょう。例えば、入力が s = abaa の場合、出力は 8 になります。これは、部分文字列として [a, b, ab, ba, aa, aba, baa, abaa] の8種類が存在するためです。解法のアプローチ:トライ木(Trie)を使うこの問題は、トライ木と呼ばれるデータ構造を使うことで効率的に解くことができます。トライ木とは、文字列の集合を木構造で表現したもので、共通の接頭辞を持つ文字列同士が同じ経路を共有できるのが特徴です。これにより、重複する部分文字列を自動的にまとめて管

  2. Pythonでn個のノードから構成できる二分探索木(BST)の数を求める方法

    問題の概要互いに異なるn個のノードが与えられたとき、それらを二分探索木(BST:Binary Search Tree)として配置する方法が何通りあるかを求めることを考えます。二分探索木には「左部分木には常に親より小さい値が、右部分木には常に親より大きい値が格納される」という重要な性質があります。この問題を解くには、カタラン数(Catalan Number)を利用します。カタラン数 C(n) は、n個の異なるキーから構成できる二分探索木の総数を正確に表すことが知られています。計算式は次のとおりです。$$C(n)=\frac{(2n)!}{(n+1)!\times n!}$$例えば、入力が n =