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

Pythonで解く「遠いバーコード」問題:隣接する要素が重複しないように並べ替えるアルゴリズム

問題の概要

倉庫に一列に並んだバーコードがあるとします。i番目のバーコードは barcodes[i] で表されます。このバーコードを並べ替えて、どの2つの隣接するバーコードも同じにならないようにするのが課題です。

例えば、入力が [1,1,1,2,2,2] の場合、出力は [2,1,2,1,2,1] のようになります。このように、同じ数字が隣り合わない配置を作ることができれば正解です。

解法のアプローチ

この問題を解くためには、以下の手順に従います。

  • 辞書(マップ)d を作成する
  • バーコード配列内の各数値の出現頻度を d に記録する
  • 空のリスト x を用意する
  • d のすべてのキーと値のペアを x に挿入する
  • インデックス i を 0 で初期化する
  • barcodes と同じ長さのリスト result を作成し、0 で埋める
  • x を出現頻度に基づいてソートする
  • i が result の長さ未満である間、以下を繰り返す
    • result[i] に x の最後のエントリの要素を代入する
    • x の最後のエントリの頻度を1減らす
    • 頻度が0になった場合、そのエントリを x から削除する
    • i を2ずつ増やす
  • 次に i を 1 に設定し、同様の処理を奇数番目の位置に対して繰り返す
  • 最後に result を返す

ポイントは、まず偶数番目の位置(0, 2, 4...)から頻度の高い要素を詰めていき、その後奇数番目の位置(1, 3, 5...)を埋めるという戦略です。これにより、最も出現回数の多い要素が隣り合うことを確実に防げます。

実装例

それでは、実際のコードを見て理解を深めましょう。

class Solution(object):
   def rearrangeBarcodes(self, barcodes):
      d = {}
      for i in barcodes:
         if i not in d:
            d[i] = 1
         else:
            d[i]+=1
      x = []
      for a,b in d.items():
         x.append([a,b])
      i = 0
      result = [0]*len(barcodes)
      x = sorted(x,key=lambda v:v[1])
      while i <len(result):
         result[i] = x[-1][0]
         x[-1][1]-=1
         if x[-1][1]==0:
            x.pop()
         i+=2
      i=1
      while i <len(result):
         result[i] = x[-1][0]
         x[-1][1]-=1
         if x[-1][1]==0:
            x.pop()
         i+=2
      return result
ob = Solution()
print(ob.rearrangeBarcodes([1,1,1,2,2,2]))

入力

[1,1,1,2,2,2]

出力

[2, 1, 2, 1, 2, 1]

コードの解説

このアルゴリズムの計算量を確認しておきましょう。

  • 時間計算量: O(n log n) — 出現頻度のソートに O(k log k)、要素の配置に O(n) かかります(k はユニークな要素数)。
  • 空間計算量: O(n) — 頻度辞書と結果リストのための追加メモリが必要です。

頻度の高い要素から優先的に間隔を空けて配置することで、どのような入力に対しても「隣接する要素が重複しない」という条件を満たす並べ替えが保証されます。これは貪欲法(グリーディ法)の一種であり、シンプルながら非常に効果的な手法です。

  1. 【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説

    はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが

  2. PythonでQuine(クワイン)プログラムを書いてみよう

    「Quine(クワイン)」とは、入力を一切受け取らずに、自分自身のソースコードを出力する特殊なプログラムのことです。一見すると不思議な自己言及的な仕組みですが、実装にはいくつかの厳格なルールがあります。最も重要な条件は、プログラム内部からソースコードファイルを読み込んではいけないという点です。つまり、純粋にコード自身の論理だけで自分の内容を再現しなければなりません。 サンプルコード Pythonでは、わずか1行でQuineを実現できます。 a=a=%r;print (a%%a);print (a%a) 実行結果 a=a=%r;print (a%%a);print (a%a) ご覧のとお