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

Pythonでリスト全体がソートされるように分割できるサブリストの最大数を求めるアルゴリズム

問題の概要

数値のリスト nums が与えられたとします。このリストは複数の部分リスト(サブリスト)に分割でき、それぞれの部分を個別にソートすることが可能です。ここで求めたいのは、分割・ソートを行った後にリスト全体がソート済みの状態になるような、部分リスト数の最大値です。

例えば、入力が nums = [4, 3, 2, 1, 7, 5] の場合、答えは 2 になります。[4, 3, 2, 1][7, 5] の2つの部分リストに分割し、それぞれをソートすれば [1, 2, 3, 4, 5, 7] という完全にソートされたリストが得られるためです。

解法の考え方:累積和による分割境界の検出

この問題は「累積和」を使うことでシンプルに解けます。元のリストとソート済みリストを先頭から同時に走査し、ある位置までの累積和が一致した時点で、そこを有効な分割境界と判断します。

なぜこれで正しく判定できるのでしょうか。ある位置で累積和が一致するということは、その位置までの要素の集合が元のリストとソート済みリストで同一であることを意味します。つまり、その境界より前の部分だけを独立にソートしても、後続の要素との相対的な順序には影響せず、結果として全体が正しくソートされるのです。

アルゴリズムの手順

  • count を 0 で初期化する
  • main_sum(元のリストの累積和)と sorted_sum(ソート済みリストの累積和)を 0 で初期化する
  • nums の各要素 x と、ソート済みリストの対応する要素 y に対して以下を繰り返す:
    • main_sumx を加算する
    • sorted_sumy を加算する
    • 両者の値が等しければ count を 1 増やす(分割境界を発見)
  • 最終的な count を返す

実装例(Python)

class Solution:
    def solve(self, nums):
        count = 0
        main_sum = sorted_sum = 0

        for x, y in zip(nums, sorted(nums)):
            main_sum += x
            sorted_sum += y
            if main_sum == sorted_sum:
                count += 1

        return count

ob = Solution()
nums = [4, 3, 2, 1, 7, 5]
print(ob.solve(nums))

入力

[4, 3, 2, 1, 7, 5]

出力

2

計算量の評価

このアルゴリズムの時間計算量は O(n log n) です。ボトルネックは最初のソート処理であり、その後の走査は単一のループで完結します。空間計算量はソート済みリストのコピーが必要なため O(n) となります。累積和の一致という直感的な指標だけで境界を検出できる点が、この解法の美しさと言えるでしょう。

  1. Pythonでリスト内の最小値を見つける方法を解説

    この記事では、リストの中から最小の数値を見つける方法について、具体的なサンプルコードとともに詳しく解説します。問題の概要問題: 数値のリストが与えられたとき、その中に含まれる最も小さい数値を画面に表示すること。この問題を解くアプローチは主に2つあります。ひとつは sort() メソッドを使ってリストを昇順に並べ替え、先頭の要素(インデックス0)を取得する方法。もうひとつは、Pythonに標準で用意されている組み込み関数 min() を使う方法です。それぞれ順番に見ていきましょう。方法1:sort()メソッドで並べ替えて最小値を取得するまずはリストを昇順にソートし、先頭の要素を取り出す方法です。

  2. Pythonでリスト内の最大値を見つける方法|sort()とmax()の2つのアプローチ

    この記事では、リストの中から最大の数値を見つけるための解決策とアプローチについて詳しく解説します。問題の概要数値のリストが与えられたとき、その中から最大の要素を見つけ出す必要があります。Pythonでは、主に以下の2つの方法でこれを実現できます。ソート(並べ替え)を利用する方法組み込み関数 max() を利用する方法アプローチ1:sort() 関数を使う方法リストを sort() メソッドで昇順に並べ替えると、リストの最後の要素(インデックス -1)が必ず最大値になります。サンプルコードlist1 = [18, 65, 78, 89, 90] list1.sort() # メイン処理 prin