タスク1
与えられた:シーケンスに規則性を持つユニークなオブジェクトのリスト(簡単にするために数字を取ります)。
制限事項:
- 10 ^ 5までの要素の数。
- 新しいリストを作成するのは費用がかかるため、同じリストを変更する必要があります。
リストの要素が同じ場所にないようにリストの要素を混合する必要があります。また、シーケンス内のパターンに違反しています。つまり、単純に要素を右または左に循環的にシフトするだけでは不十分です。
解決策:
リスト内の要素の数をnとします。 各要素がその位置にないことを確認する必要があるため、(n-1)から1に変化するインデックスiを持つ各要素の乱数を生成します-0からiのインデックスは含まれません。 したがって、現在のインデックスiと等しくないランダムインデックスjを受け取った後、iとjの位置にある要素を交換します。
例:
リスト= [1,7,5,2,6]。
アルゴリズムをわかりやすくするためにトレーステーブルに入力します。iはrightIndexで示され、jはleftIndexです。
rightIndex
| leftIndex
| 一覧
|
4
| 1
| [1,6,5,2,7]
|
3
| 2
| [1,6,2,5,7]
|
2
| 0
| [2,6,1,5,7]
|
1
| 0
| [6,2,1,5,7]
|
最初のリストと、アルゴリズムの実行から生じたリストを書き出します。
[1,7,5,2,6]
[6,2,1,5,7]
ご覧のとおり、すべての要素が別の場所に移動しており、その場所に残っている要素は1つではありません。 気づいた場合、rightIndexは常にリストの最後のインデックスから1に変わります。そして、leftIndexはランダムに生成されるため、ループの各繰り返しでの対応するrightIndexよりも厳密に小さくなります。 この特性により、最終結果が達成されます。
上記のメソッドをC#で記述します。 任意のオブジェクト(数値、文字列、カスタムデータ型)で使用できるようにパラメーター化します。
// , public static void Shiffle<T>(this IList<T> list) { var random = new Random(); int maxIndex = list.Count - 1; for (int i = 0; i < maxIndex; i++) { int rightIndex = maxIndex - i; int leftIndex = random.Next(0, rightIndex); list.Swap(leftIndex, rightIndex); } }
// public static void Swap<T>(this IList<T> list, int index1, int index2) { T c = list[index1]; list[index1] = list[index2]; list[index2] = c; }
この関数をリポジトリに投稿しました。 GitHubリンクはこちら 。
アルゴリズムの正しい操作に同意しない場合、または完全に理解していない場合は、コメントを記入して、回答します。
あなたがより速い解決策、またはより単純な解決策(自然に説明し、自然にそのような制限がある)を持っているなら、コメントで示してください、私は感謝します。