teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

HashMapを使った部分シャッフル追加

2016/03/18 13:40

投稿

YsMana
YsMana

スコア257

answer CHANGED
@@ -83,4 +83,65 @@
83
83
  ```
84
84
 
85
85
  1億個から30個欲しい様な場合は連想配列(疎な配列が実現できるなら何でもいいです)を使って、
86
- 初期状態空、キーに対応する要素が存在しない場合はキーと同じ要素が入っていると見なして同じように部分シャッフルをかければできそうな気がします。
86
+ 初期状態空、キーに対応する要素が存在しない場合はキーと同じ要素が入っていると見なして同じように部分シャッフルをかければできそうな気がします。
87
+
88
+ #追記
89
+ HashMapを使った広範囲からのランダム取得が可能なコードを書いてみました。
90
+ 重複時のリトライがないので、1000個中1000個とかでもたぶん安定した性能になると思います。
91
+
92
+ ```Java
93
+ import java.util.Random;
94
+ import java.util.HashMap;
95
+
96
+ class Shuffle {
97
+
98
+ private int list_len;
99
+ private HashMap<Integer,Integer> list;
100
+
101
+ public Shuffle()
102
+ {
103
+ }
104
+
105
+ public void SetList(int num)
106
+ {
107
+ list = new HashMap<Integer,Integer>();
108
+ list_len = num ;
109
+ }
110
+
111
+ public int[] GetShuffleList(int snum){
112
+ int pick;
113
+ int[] s_list;
114
+ Random rnd = new Random();
115
+ s_list = new int[snum];
116
+
117
+ for(int i = 0;i < snum;i++){
118
+ pick = rnd.nextInt(list_len);
119
+ s_list[i] = list.containsKey(pick) ? list.get(pick) : pick; //ランダムで要素を取得
120
+ list_len--; //取り出したので長さを減らす
121
+ list.put(pick, list.containsKey(list_len) ? list.get(list_len) : list_len ); //最後尾の要素を持ってくる(list[pick]はもういらない)
122
+ }
123
+ return s_list;
124
+ }
125
+ }
126
+
127
+ class test02 {
128
+ public static void main(String args[]){
129
+ Shuffle s1 = new Shuffle();
130
+
131
+ s1.SetList(20);
132
+ int[] s_list = s1.GetShuffleList(10);
133
+ System.out.println("20 => 10");
134
+ for(int i = 0;i < s_list.length;i++){
135
+ System.out.println(s_list[i]);
136
+ }
137
+
138
+ s1.SetList(100000000);
139
+ s_list = s1.GetShuffleList(10);
140
+ System.out.println("100000000 => 10");
141
+ for(int i = 0;i < s_list.length;i++){
142
+ System.out.println(s_list[i]);
143
+ }
144
+ }
145
+ }
146
+ ```
147
+