Pythonの一般的に使用されるアルゴリズム(6) - 貪欲アルゴリズム、ユークリッドアルゴリズム

1、貪欲アルゴリズム

  (も貪欲アルゴリズムとして知られている)貪欲アルゴリズムは常に現在で作られた問題解決には、最良の選択であると表示されたとき、ということを意味します。彼は地元の意味での最適解をしたときに、他の言葉では、最高の全体として考慮されません。

  貪欲アルゴリズムは、最適解を保証するものではありませんが、いくつかの問題に貪欲アルゴリズムの解は最適解です。裁判官が計算する貪欲なアルゴリズムを使用するかどうかの質問へ。バックトラックは、選択しようとすることです。貪欲アルゴリズムと他のアルゴリズムは、すべての問題の各サブ問題の解決策を貪欲に選択するのではなく、現在の最善の解決策(グローバル最適解)を取得するために統合されているより多くの明らかな違い、動的計画されています道は、間違った選択した場合は、「戻る」ことができ、つまり、再選択する別の試みに戻ってきます。

1.1変更の問題を与えます

  その店舗の所有者が変更を与える必要があり、Nドルの額面のコインがコインの必要最小限の数の変更を行う方法100元、50元、20元、5元、1元であると仮定?(注:$ 10宗派はありません)

  376元を探している場合はどうそれを変更?100 * 50 * 1 + 3 + 5 + 20 * 1 * 1 * 1 + 1 = 375

  コードは以下の通りであります:

#Tは、店舗の金種に何らかの変化を表す
T = [100、50、20である,. 5 ,. 1] 

#nはn型元表す
DEF変更(T、N)
    レンジにするため、M = [0 _を(LEN(T)) ] 
    I、列挙(T)でのお金のために:
        M [I] = // N分割マネー位切り捨て
        N = N%マネー#モジュロ分割
    リターンM、N- 

プリント(変更(T、376である))(# [3、1、1、1、1]、0)

1.2ナップザック問題

  一般的なナップザック問題のナップサックといくつかは、整数ナップサック問題を抱えています。大体このような問題の説明。

  ストア内の泥棒は、N品、商品Viを元のi番目の値、重いのWi kgのある発見しました。彼はできるだけ高い値を奪うように望んでいるが、彼のバックパックは、Wキロのものを保持することができます。彼はそれらの商品を取る必要がありますか?

  0-1バックパック:商品の場合、または泥棒は彼の整合性を片付け、または去ります。あなただけの一部を取ることができない、または商品が複数(商品地金)を取るために

  バックパックのスコア:商品の場合は、泥棒がその一部を奪うことができます。(コモディティ金沙)

例えば:

  貪欲アルゴリズムが最適解を得ることができるかどうかのスコアのための0-1バックパックやリュックサック、?なぜ?

   明らかに、小数ナップサックのための貪欲アルゴリズムは、必ず最適解を得るために、我々は単位重量あたりの各項目の値を計算し、その後、彼らは降順でソートされ、その後、アイテムを取るようになった、ちょうどあなたが完全に装甲できる項目のすべての種類のふり機器のすべてがフルバックパックまで内側部分にインストールされていない場合は下に行きます。

  この問題のために、それは確かに記入しない明確なナップサックです。でもすることができますが、すべての0-1ナップザック問題を満たすことができない偶然であれば。0-1ナップザック(ナップザック問題既知の整数)は、2つに分けることができる:一つは限ら(有界)されている各タイプの品目の数です。一つは、(無制限)の無限の数である、つまり、あなたは、これら二つの貪欲な戦略を使用することはできません、できるだけ多くを持っていると思います。0-1バックパックは、最初の整数ナップサック問題の典型です。

  バックパックのコードの実装をスコア:

各タプルは#製品(価格、重量)を表す
商品= [(60、10)、(100、20)、(120、30)] 
まず、製品をソートする必要位、これはもちろんソートされる
商品を.sort(ラムダキー= X:[1] X [0] / Xが、=真逆方向)

#Wはナップザック容量表す
DEFのfractional_backpack(商品、W)を:
    #mは、各記事の数を離れ表し
    total_v = 0 
    、M = [0 _中範囲(LEN(財))] 
    列挙(財)にI、(賞、重量)の場合:
        > =重量W IF:
            。M [I] = 1 
            total_v + =賞
            W - =重量
        #mを[I] 1 IF = W>他重量=重量/ W。
        他:
            M [I] = W /重量
            total_v + M = [I] *賞
            W = 0 
            BREAKの
    戻りM、total_v

RES1、RES2 = fractional_backpack(商品、50)
プリント(RES1、RES2)#1 [1、1、0.6666666666666666]

質問の1.3スプライシング最大数

  文字列としてスプライス整数ようにスプライスされ、非負Nがあります。ステッチ取得する方法の最大の整数を作ることができますか?

  例えば:32、94、128、1286、6、71は最大の整数94716321286128にスプライスすることができます。

     注1:サイズと文字列の比較の整数は、デジタルサンプルサイズを比較!文字列の比較は最初の長い、どのように短い文字列比較の最初の、大きな大きな、しかし、文字列の大きさを見ているのですか?例えば、128と1286を比較します

  次のようにアイデアは以下のとおりです。

#単純:ビットように両者を比較
A =「96」
B =「97」

A + B IF A>他B B + 

以下の比較の範囲のビット数が貪欲アルゴリズムを使用する方法、がある場合#それは?
WE#変換考え、文字列の連結、比較結果

A = '128' 
B = '1286' 

追加#列
A + B = '1281286' 
B + A = '1286128' 

A + B + A IF B> B +をそれ以外のB + A

  スプライシングデジタルコードは次のとおりです。

functoolsはcmp_to_keyインポートから

のLi = [32、94、128、1286、6、71] 

DEF xy_cmp(X、Y): 其中1表示のx> yと、-1,0同理
    もしX + Y <Y + X:
        1戻り
    :ELIF X + Y> Y + X 
        -1を返し
    他:
        戻り0 

:デフnumber_join(LI)
    のLi =リスト(マップ(STR、リチウム))
    li.sort(キー= cmp_to_key(xy_cmp)) "リターン"。参加(LI)

プリント(number_join(LI))#94716321286128

1.4活動の選択

  唯一のアクティブな使用のために一度にスペース、およびスペースの同じ部分を取る活動は、nがあるとします。

  各アクティビティは、開始時刻と終了時刻のSi Fiの(整数として表題時間)のSi、FI)ゾーン占有スペースにおいて活性を示しました。(注:左右開閉)

  Q:どのような活動で最も数の会場の活動を手配することができますか?

   貪欲結論:最初の活動の終わりには、最適なソリューションの一部でなければなりません。

  証明:活動のすべての活動の一端を仮定し、bがイベントの第一の端部における最適なソリューションです。

  = bの場合、結論を設定しました

  != Bは、終了時刻後タイムアウトの終了より定数bは、この時点では、Bにおける最適解に置き換えられた場合、一定時間は、このように置き換える、最適解における他の活動と重複しませんソリューションは、最適なソリューションです。

   コードは以下の通りであります:

#タプルは(時刻、終了時刻を開始)イベントを表す
アクティビティ= [(1 ,. 4)、(3 ,. 5)、(0 ,. 6)、(。5 ,. 7)、(3 ,. 9)、(。5 、9)、(6,10)、(8,11)、
              (8,12)、(2,14)、(12,16)] 

#活動ソート時間の終わりに従っていることを確認し、我々は、ソートするために所有することができ
activities.sort(ラムダキー= X:Xの[1])

DEFのactivity_selection(A): 最初、[0]は必ずの一端
    のRES = [0]] ためのIレンジ(1、LEN(A) ):
        [I] [0]> =のRES [-1] [1] IF:前回選択の現在アクティブ以下活性末端位開始時刻
            位競合ない
            res.append([I])は
    RESを返します

activity_selectionの=のRES(活動)
を印刷(RES)

1.5最大のサブシーケンスと

  サブアレイの最大値を求める問題は、整数配列(配列要素が正で負担)、連続的に最大の和を求めるサブアレイが与えられます。トラバースする貪欲なアルゴリズムを用いて、一つ次の1。

 コードは以下の通りであります:

DEF maxSubarray(LI):
    S_MAX、s_sum = 0,0 
    範囲内のiについて(LEN(LI)):
        s_sum + =リチウム[I] 
        S_MAX = MAX(S_MAX、s_sum)
        場合s_sum <0:
            s_sum = 0 

    戻りS_MAX

2、ユークリッドアルゴリズム - 最大公約数

2.1定義、最大公約数

  約数:整数bは整数で割り切れる場合は、B、Bの除数が呼び出されると、複数と呼ばれます。

  最大公約数(最大公約数):二つの整数、Bを考えると、2つの数のすべての公約数の最大値は、の最大公約数です。

  例:12と16の最大公約数は4です。

次のように2.2ユークリッドアルゴリズムは次のとおりです。

  ユークリッドアルゴリズムはまた、2つの正の整数、B最大公約数を計算するユークリッドのアルゴリズムを知られています。

  • E:2つの正の整数、bは設けられており、それはA> Bが知られています
  • E1:オーダーR =%のB( '%' 代表余り)
  • E2:R = 0(すなわち、nはMによって割り切れる)、操作の終了は、結果がNである場合に
  • E3:別段= B、B = Rをさせると、ステップE1に戻ります。

  ((またはモジュラ算術モジュロ演算設けられたGCDの代わりに、B)の最大の共通の除数及びB、MOD()の代わりに)ユークリッドアルゴリズムを用いた式と等価となるよう。

 GCD(A、B)= GCD(B、MOD B)= GCD(B、%b)は

  すなわち、mは、nはその最大公約数で除算する剰余(R)とNの最大公約数に等しいです。  

  例えば:GCD(60、21)= GCD(21、18)= GCD(18、3)= GCD(3、0)= 3

  モジュロ18は、3,18〜18のモジュロ3 0、2つの数の3最大公約数上同じ理由の21対6021であることを意味します。

2.3は、ユークリッドは式ことを証明しました

  我々は2つのステップで証明しました。そのGCD証明する最初のステップ(b)はBの除数、bは%です。第二段階は、これは最大公約数であることを証明します。

1、GCD Bの(b)は、数、慣例の%のBを実証

  1、任意の2つの正の整数がDに最大公約数を、持っているので。

  2、A、Bは、最大公約数dでのK2 *のD(K1、K2は、2つの定数である)= = K1の* dをbとして表され

  3、せ= K * B + C(すなわち、サプライヤB k個のI Cで割った)、次いで= K1の* dをB = K2の* dの2つの式、B、式を代入することにより精製して:

C = A - K * B = K1 * D - のk * K2の* dを、次いでC =与えるために、共通の除数Dを再抽出した(K1 - K2 * K)* D、示し、Cは%Bをd有しますこの数については、我々は、任意の2つの数値を設定するために始めたので、公約数dを持っているので、GCD(a、b)はBの除数、bは%です。

  GCD(A、B)= GCD(B、MOD B):4証拠を与えるために、最大公約数dの倍数でCすることによって得ることができます。だから、ステップE3があるので、大きな数は、剰余R、実現次元削減の少ない数に置き換えMNであってもよいです。 

2、我々は公約数が最も大きい模索ことを証明

  、k個* K2 * DB = K2の* dを、私たちは唯一K1-k個* K2とを証明する必要がある - 1は、数学は我々がそのC(%のB)= K1 * Dを知っている、厳密フロント必要性、厳格な規律ありますk2は互いに素することができます。

  k個* K2 = Q *トンのK2 =のp *トン、代わりにk1は=(q個の*トン+ K * k2とを与えるために、= K1の* dのこの始まりを繰り返し - 2は、矛盾を使用することができる、我々はk1は仮定します)* D、得られた乗算の分配法則再利用:= Qの*さt *のD + K我々が発見* k2との* dを、K2 * Dは、それに代えて、Bは、= Q *さt *のD + Bを得ました* D

  3、我々は= P * tは、B = K2の* dを代入開始B = P *はT * dを与えるために、次いで、式A = Qの*さt *のD + B * dの子孫であったがK2であろう。 。A = Q * T * D + P * T * D共通因子抽出:* T * D =(Q + P)を

  4、その後、B =のp *トンの* dは、その最大公約数がt * dのなったと仮定が逆成功に証拠れていないので、矛盾を開始するために比較しました!

2.4、どのように最大公約数を計算するには?

  1、ユークリッド:ユークリッドアルゴリズム(ユークリッドアルゴリズム)

  2.「九章算術」:テクニックを下げます

   コードは以下の通りであります:

#递归法:保证A> B 
GCD DEF(B):
    もしB == 0:
        戻り
    他の:
        リターンGCD(B、%b)は

#递推法
DEF gcd1(B):
    もし< B:
        B = B、
    一方、B> 0:
        R =%Bは
        A = B 
        B = Rの
    戻りA

  これは擬似再帰的であるため、その時間計算量は高くありません。

2.5アプリケーション:小数の計算

   ユークリッドアルゴリズムのクラスを使用してスコアは、四則演算のスコアをサポートします。

   コードは以下の通りであります:

#_ * _コード:UTF-8 _ * _ 

クラスフラクション:
    DEF __init __(自己、B):
        self.a = 
        self.b = B 
        、X = self.gcd(a、b)は
        self.a / = X 
        セルフ.B / = X 

    #最大公约数
    DEF GCD(自己、B)
        :B> 0ながら
            R =%Bは
            A = B 
            B = rが
        戻り

    位最小公倍数
    DEF ZGS(自己、B)。
        #12 16 - > 4 
        #3 * 4 * 4 = 48 
        、X = self.gcd(a、b)は
        戻り(*のB / X) 
加法的内置方法
    DEF __add __(自己、他):
        #1/12 + 1/20 
        A = self.a 
        B = self.b 
        C = other.a 
        D = other.b 
        fenmu = self.zgs(B、D)
        femzi = *(fenmu / B)+ C *(fenmu / D)
        リターン画分(femzi、fenmu)

    DEF __str __(自己):
        戻り"%D /%D" %(self.a、self.b)


F =画分(30、16)
印刷(F)

 2.7ユークリッドアルゴリズムの欠点

   ユークリッドアルゴリズムは2つの伝統的な方法の最大公約数の数を計算することで、理論と実践的な効率性の面で非常によくあります。この欠陥は、プライムタイムでは比較的小さいが、致命的な欠陥があり、通常、大きな素数が明らかにされたときにのみ感じています。

  通常の実用的なアプリケーションの整数はほとんど、そのような整数を、2つの非常に単純な計算の間に、金型の数を(もちろん、今128可)64ビットを超えません。32を超えないプラットフォーム、32ビットのワード長のために二つの整数は、一つだけの命令サイクルを法として計算し、金型64以下の整数を算出するだけでなく、わずか数サイクル。より大きな素数のために、この計算は、ユーザによって設計されなければならない、64の整数にわたって2つのモードを計算するために、ユーザは、マルチビットの分割を採用する必要がある可能性があり、この、手動テスト商業オペレータの処理と同様ですプロセスだけでなく、複雑ですが、また多くのCPU時間を消費します。128ビットの素数の数を計算するために必要な現代の暗号アルゴリズムの場合について上記除算およびモジュラスを放棄する熱心ようなプログラム設計を富みます。

  スタインアルゴリズムは、整数のみ算術シフトと減算J.スタイン1961インディアンによってこの欠陥ユークリッドアルゴリズム、スタインに良い解決策を提案して有効スタインアルゴリズムを実証するために、まず以下のことに留意しなければなりません結論:

  GCD(A)=、それは、それ自身の数であり、依然として独自の公約数です。
  GCD最大公約数の計算であり、乗算演算を交換することができる(KA、KB)= k個のGCD(a、b)は、。特に、K = 2は、2であっても必ずしも割り切れる最大公約数2つを説明します。
  k及びbが互いに素であるとき、GCD(KA、B)= GCD(a、b)は、わずか約2:1つのを含む因子のうちの、すなわち数が共通に影響を及ぼしません。特に、K = 2は、偶数および奇数の最大公約数を計算する説明は、偶数は、最初の2つによって分割することができる場合。

   コードは以下の通りであります:

DEF gcd_Stein(B):   
    <Bであれば
        、B = B、A 
    (0 == b)は次の場合
        、戻りA 
    %2 == 0およびB%2 == 0の場合:
        リターン2 * gcd_Stein( / 2、B / 2)
    %2 == 0の場合:
        戻りgcd_Stein(/ 2、B)
    B%2 == 0の場合:
        gcd_Stein(B / 2)を返す
    
    gcd_Stein((A + Bを返します) / 2、( - B)/ 2)

参照します。https://www.cnblogs.com/jason2003/p/9797750.html

https://www.cnblogs.com/Dragon5/p/6401596.html

おすすめ

転載: www.cnblogs.com/qq575654643/p/11753388.html