ムーア投票法(多数決法)

ムーアの投票:解決すべき主な問題は、任意の数の候補者の中から投票数が最も多いものをどのように選択するかです(投票は順不同です)。

时间复杂度:O(N)
空间复杂度:O(1)

視覚的な説明:
ここに画像の説明を挿入

このような写真を想像してみてください。会議場には投票する代表者がたくさんいて、それぞれに選択した候補者の名前が書かれた看板があります。すると、意見が合わない(選ばれた候補者が違う)二人が同時に戦い、ノックダウンします。明らかに、1人が他のすべての票を合わせたよりも多くの票を持っている場合、候補者は「戦争」に勝ち、混乱が終わると、最後に残っている代表者(複数の場合があります)はほとんどの人がいるキャンプから来ますスタンド。しかし、すべての候補者の投票が過半数ではない場合(投票の半分以下)、最後にそこに立っている代表者(1人)がすべての投票の過半数を表すことはできません。したがって、最後に立った場合、投票結果が有効かどうかを判断するために、彼が選んだ候補者の投票が半分以上(落ちたものを含む)であるかどうかを数える必要があります。

アルゴリズムの手順:

ペアリングステージとカウントステージの2つのステージに分かれています。
対決ステージ:投票の異なる2人が互いに戦い、同時にノックダウンします。残りの人々が同じキャンプにいる場合、つまり、同じ投票、終わり。開票
段階:最後に残った人の投票を数えて、投票が総投票数の半分以上であるかどうか、および投票が有効かどうかを判断します。

対立段階の簡素化:戦うため
ここに画像の説明を挿入
に異なる票を投じる必要はありません。より文明的なアプローチを取ることができます。非常に賢い人が出席しました。彼はすべての票をスキャンし、頭の中で2つのことを思い出しました。現在の候補者の名前カンドと対応するカウンターk(kはカンドの票数ではなく0に初期化されます)。全員の投票を見るときは、まずkが0かどうかを確認します。0の場合は、すぐに見た候補者の名前に候補者を更新し、kの値を1に更新します。このとき、kは候補者の更新後のキャンプ。各人の投票のプロセスを観察します。人の投票がカンドと同じ場合、kの値は+1に設定されます。それ以外の場合、kの値は-1に設定され、最後のカンドが選挙に勝つ可能性があります。彼の総投票数が半分を超えているかどうかも数える必要があります。

アルゴリズムの証明:

ここに画像の説明を挿入
代表者がn人いるとします(1人、1票、総投票数はn)。賢い人がi番目の代表者の投票を見ると(1≤i≤n)、彼が以前に見たすべての投票は2つのグループに分けることができ、最初のグループはk人の代表者が率直に同意します。他のグループは投票はペアですべてのオフセットが可能です(異なる投票)。すべての投票が処理され、過半数があれば、候補者が選出されます。
candとは異なるが、n / 2票を超えるxがあるとします。ただし、2番目のグループの投票はすべてペアで相殺できるため、xの数が最大の投票数は(n − k)/ 2です。したがって、xは半分を超える最初のグループの投票を受け取る必要がありますが、最初のグループは投票のグループそれらはすべて率直であり、矛盾があり、仮説は成り立たない。
したがって、過半数が存在する場合、率直なものがその1つです。

アルゴリズムのデモ:
Webリンク

コードフレームワーク:

    public int majorityElement(int[] nums) {
    
    
        int cand = 0, k = 0;
        //对抗阶段,最后的cand有可能就是选票最多的候选人
        for (int i = 0; i < nums.length; i++){
    
    
            if(k == 0){
    
    
                cand = nums[i];
                k = 1;
            }
            else {
    
    
                if(nums[i] == cand){
    
    
                    k += 1;
                }
                else {
    
    
                     k--;
                }
            }
        }
        //计数阶段,看是否是大多数
        int cnt = 0;
        for (int num:nums) {
    
    
            if(num == cand)
                cnt++;
        }
        //表示未超过一半
        if (cnt <= nums.length/2){
    
    
            cand = -1;
        }
        return cand;
    }

おすすめ

転載: blog.csdn.net/Puppet__/article/details/115296697
おすすめ