Pythonでリストを合計が等しくAの全要素がBより小さい2つのグループに分割できるか判定する方法
問題概要
数値のリスト nums が与えられたとき、このリストを2つのグループ A と B に分割できるかどうかを判定するプログラムを作成します。分割には以下の2つの条件を満たす必要があります。
- グループ A の合計とグループ B の合計が等しいこと
- グループ A 内のすべての数値が、グループ B 内のどの数値よりも厳密に小さいこと
例えば、nums = [3, 4, 5, 12] という入力の場合、出力は True になります。A = [3, 4, 5]、B = [12] とすれば、両方の合計が12となり、すべての条件を満たすからです。
解決アプローチ
この問題は、リストをソートして先頭から累積和を確認していくことで効率的に解けます。手順は以下の通りです。
- リスト nums をソートする
- 全要素の合計 total を求める
- 累積和 s を 0、インデックス i を 0 で初期化する
- i がリストの長さ未満である間、次を繰り返す:
- n := nums[i] とする
- i が範囲内かつ nums[i] == n の間、s に nums[i] を加算し i を進める(同じ値の要素をまとめて処理)
- s == total - s であれば True を返す
- ループ完了後は False を返す
ここでのポイントは、ソート済みリストに対して同じ値ごとにまとめて累積和を取る点です。これにより、A と B の境界が同一の値をまたぐことがなくなり、「A の最大値 < B の最小値」という条件が自動的に保証されます。
実装例
class Solution: def solve(self, nums): nums.sort() total = sum(nums) s = 0 i = 0 while i < len(nums): n = nums[i] while i < len(nums) and nums[i] == n: s += nums[i] i += 1 if s == total - s: return True return False ob = Solution() nums = [3, 4, 5, 12] print(ob.solve(nums))
入力
[3, 4, 5, 12]
出力
True
計算量の目安
ソートに O(n log n)、その後の線形走査に O(n) を要するため、全体の時間計算量は O(n log n) となります。ソートをインプレースで行えば、追加の空間計算量は O(1) で抑えられます。
-
Pythonで特定の操作を繰り返して全要素を等しくする最小手順を求めるプログラム
数値のリスト nums が与えられ、すべての値を等しくすることを考えます。ここで「リストから1つの要素を選び、それ以外のすべての値を1ずつ増やす」という操作が許されているとします。このとき、すべての要素の値を等しくするために必要な最小の操作回数を求めます。 たとえば、入力が [2, 4, 5] の場合、出力は 5 になります。 解法のポイント 「選んだ要素以外を1ずつ増やす」という操作は、相対的な差に注目すると「選んだ1つの要素だけを1減らす」操作と同じ効果があります。そこで、各要素をリストの最小値まで揃えることを考えると、各要素 num に必要な操作回数は num - min_val となり
-
Pythonでソート後に正しい位置にある要素の数をカウントする方法
問題の概要数値のリスト nums が与えられたとき、そのリストをソートした場合に元の位置から動かない要素(正しいインデックスに配置される要素)がいくつあるかを求めるプログラムをPythonで作成します。例えば、入力が [2, 8, 4, 5, 11] の場合を考えてみましょう。このリストを昇順にソートすると [2, 4, 5, 8, 11] になります。比較すると、先頭の「2」と末尾の「11」はソート前後で同じ位置に留まっています。したがって、出力は 2 となります。解決のアプローチこの問題は、以下の手順でシンプルに解くことができます。リスト nums をソートした新しいリスト s を作成する