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

Pythonで最初と最後の要素が同じサブリストの個数を求めるプログラム


数値のリスト nums が与えられたとき、最初の要素と最後の要素が一致するサブリスト(部分リスト)の個数を求めることを考えます。

たとえば、入力が nums = [10, 15, 13, 10] の場合、答えは 5 になります。条件を満たすサブリストは次の5つです。

  • [10]
  • [15]
  • [13]
  • [10]
  • [10, 15, 13, 10]

解法のアプローチ

この問題は、各要素の出現回数を数えて組み合わせの公式を適用することで、O(n) の計算量で効率的に解けます。手順は以下の通りです。

  • 単一要素のサブリストは必ず条件を満たすため、初期値として num_sublists := len(nums) を設定します。
  • d := 空の辞書(マップ) を用意します。
  • nums 内の各要素 n について、d[n] := d[n] + 1 として出現回数をカウントします。
  • 辞書 d 内の各値 k とその出現回数 v について、v が 1 でない場合、num_sublists := num_sublists + (v−1) × v ÷ 2 を加算します。
  • 最後に num_sublists を返します。

なぜこの式で求まるのか?

同じ値が v 個あるとき、その中から異なる2つの位置を選ぶ方法は、組み合わせの公式 C(v, 2) = v × (v − 1) / 2 通りあります。選んだ2つの位置をサブリストの始点と終点にすれば、そのサブリストの最初と最後の要素は必ず一致します。これに単一要素のサブリスト分 len(nums) を加えることで、答えが得られます。

実装例

from collections import defaultdict
class Solution:
    def solve(self, nums):
        # 単一要素のサブリストは常に条件を満たす
        num_sublists = len(nums)

        # 各要素の出現回数をカウント
        d = defaultdict(int)
        for n in nums:
            d[n] += 1

        # 同じ値のペアの組み合わせ数を加算
        for k, v in d.items():
            if v != 1:
                num_sublists += (v - 1) * v // 2
        return num_sublists

ob = Solution()
nums = [10, 15, 13, 10]
print(ob.solve(nums))

入力

[10, 15, 13, 10]

出力

5

計算量

時間計算量・空間計算量はともに O(n) です。すべてのサブリストを列挙して確認する素朴な O(n²) のアプローチと比べて、大幅に高速に動作します。

  1. Pythonで最初のノードから最後のノードまでの制限付きパスの数を求めるプログラム

    無向の重み付き連結グラフがあるとします。グラフは n 個のノードを持ち、それぞれのノードには 1 から n までのラベルが付けられています。始点から終点へのパスとは [z0, z1, z2, ..., zk] のようなノードの列のことで、z0 が始点ノード、zk が終点ノードであり、隣り合うノード zi と zi+1 の間(0 ≤ i ≤ k-1)には必ず辺が存在します。パスの距離は、そのパスが通る辺の重みの総和として定義されます。また、dist(x) は「ノード n からノード x までの最短距離」を表すものとします。制限付きパス(restricted path)とは、すべての i(0 ≤

  2. Pythonで2つの二分木が完全に同じかどうかを判定するプログラム(構造と値の比較)

    2つの二分木が与えられたとき、それらが構造と値の両方の観点で完全に一致しているかどうかを確認します。このような木のペアは「双子の木(twin trees)」と呼ばれることがあります。 たとえば、次のような入力があったとします。 この場合、最初のペアに対する出力は True になります。一方、2番目と3番目のペアは、それぞれ「値が異なる」ケースと「構造が異なる」ケースに該当するため、出力は False になります。 解決のアプローチ この問題は、再帰的な手法を用いて解くことができます。具体的には、以下の手順に従います。 solve() メソッドを定義し、2つのルートノードを受け取るようにしま