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

Pythonで解く「kと-kの両方が存在する最大のkを見つける」問題

この記事では、Pythonを使って「リスト内に k-k の両方が存在するような、最大の数 k を見つける」問題の解き方を解説します。

問題の概要

数値のリスト nums が与えられたとき、k と -k がどちらもリスト内に存在するような最大の数 k を求めます。該当する要素が存在しない場合は -1 を返します。

たとえば、入力が [-5, 2, 9, -6, 5, -9] の場合、「9」と「-9」が両方存在するため、答えは 9 となります。

解法のアプローチ

この問題は、リストを正の数と負の数に分けてソートし、対応するペアを効率的に探すことで解けます。具体的な手順は以下の通りです。

  • L1:nums 内の 0 以上(正)の要素だけを集めたリストを作る
  • L2:nums 内の 0 以下(負)の要素だけを集めたリストを作る
  • L1 を降順にソートする
  • L2 を昇順にソートする
  • L1 の各要素 i について、L2 の各要素 j と比較する
    • i + j == 0 ならば、i を返す(これが現時点での最大値)
    • i + j > 0 ならば、内側のループを抜けて次の i へ進む
  • ループが完了しても見つからなければ、-1 を返す

ポイントは、L1 を降順・L2 を昇順に並べることで、大きい方から順にペアをチェックできる点です。i + j が正になった時点で、それより小さい j との組み合わせでは絶対に 0 にならないため、内側のループを打ち切ることで無駄な計算を省いています。

実装例

以下がPythonでの実装コードです。

class Solution:
    def solve(self, nums):
        L1 = [i for i in nums if i >= 0]
        L2 = [i for i in nums if i <= 0]
        L1.sort(reverse=True)
        L2.sort()
        for i in L1:
            for j in L2:
                if i + j == 0:
                    return i
                elif i + j > 0:
                    break
        return -1

ob = Solution()
nums = [-5, 2, 9, -6, 5, -9]
print(ob.solve(nums))

実行結果

入力:

[-5, 2, 9, -6, 5, -9]

出力:

9

補足:より効率的な方法

上記の二重ループ方式は分かりやすい反面、最悪の場合 O(n²) の計算量がかかります。集合(set)を使えば O(n) まで改善できます。

def solve(nums):
    s = set(nums)
    result = -1
    for x in s:
        if -x in s:
            result = max(result, x)
    return result

まずリストをセット化し、各要素 x について「-x も存在するか」を確認します。条件を満たすものの中で最大値を採用すれば、同じ答えをより高速に得られます。データサイズが大きい場合はこちらの方法がおすすめです。

  1. Pythonで二分木からノードを削除し、残りのフォレストの根を求める方法

    本記事では、二分木から特定のノードを削除した際に生じる「フォレスト(森)」の根を求めるアルゴリズムを、Pythonのコードとともにわかりやすく解説します。問題の概要二分木の根(root)が与えられ、木に含まれる各ノードは一意の値を持っているものとします。ここで、to_delete リストに含まれる値を持つノードをすべて削除すると、木はいくつかの独立した部分木、すなわち「フォレスト」へと分割されます。このとき、残ったフォレストを構成する各木の根を見つけるのが目的です。たとえば、次のような二分木が入力として与えられたとします。このとき to_delete 配列が [3, 5] である場合、値3と5

  2. 【Python入門】eval()関数で文字列を評価してオブジェクトを取得する方法

    Pythonには、文字列を引数として受け取り、それをPythonの式として評価する組み込み関数 eval() が用意されています。インタプリタは渡された文字列を有効なPython式として解析し、正しければ評価を実行した結果のオブジェクトを返します。eval()関数の基本的な使い方eval() の構文は以下のとおりです。eval(expression[, globals[, locals]])第一引数には評価対象の文字列を指定します。省略可能な第二・第三引数では、評価時に使用するグローバルおよびローカルの名前空間(辞書)を指定できます。算術式を含む文字列の評価最もシンプルな例が、算術式を含む文字