回答編集履歴
1
順序や重複を維持しないというパターンも追加
test
CHANGED
@@ -1,12 +1,24 @@
|
|
1
|
-
Listからの削除は**大変重い処理**です。これはListが「配列(array)」と言われるデータ構造であるため、インデックスアクセスがO(1)になる代わりに、削除がO(n)になってしまうからです。
|
1
|
+
Listからの削除は**大変重い処理**です。これはListが「配列(array)」と言われるデータ構造であるため、インデックスアクセスがO(1)になる代わりに、削除がO(n)になってしまうからです。ましてや、Removeで添字ではなくオブジェクトを指定する場合は、検索もO(n)になるため、さらに遅い原因になります。
|
2
|
+
|
3
|
+
|
4
|
+
|
2
|
-
|
5
|
+
つまり、オリジナルコードは削除のリスト分繰り返しているためO(n × m)です。(nはmainのサイズ、mはdeleteのサイズ)
|
3
|
-
|
4
|
-
|
6
|
+
|
7
|
+
|
8
|
+
|
5
|
-
解決策は二つほどです。
|
9
|
+
解決策は二つ(順序重複維持あり)+二つ(順序重複維持なし)ほどです。
|
10
|
+
|
11
|
+
|
12
|
+
|
6
|
-
|
13
|
+
###順序と重複を維持する場合
|
14
|
+
|
15
|
+
|
16
|
+
|
7
|
-
|
17
|
+
順序を維持し、また、重複している場合は重複したままにする場合です。
|
8
|
-
|
18
|
+
|
19
|
+
|
20
|
+
|
9
|
-
###連結リストを使う
|
21
|
+
####連結リストを使う
|
10
22
|
|
11
23
|
|
12
24
|
|
@@ -18,11 +30,11 @@
|
|
18
30
|
|
19
31
|
|
20
32
|
|
21
|
-
なぜなら、Removeで該当の
|
33
|
+
なぜなら、Removeで該当のオブジェクトを探す検索がO(n)の計算量が必要になるからです。削除が速いだけで見つけるのが速くなるわけではありません。結局O(n × m)になってしまいます。
|
22
|
-
|
23
|
-
|
24
|
-
|
34
|
+
|
35
|
+
|
36
|
+
|
25
|
-
###新たに配列を作る
|
37
|
+
####新たに配列を作る
|
26
38
|
|
27
39
|
|
28
40
|
|
@@ -30,6 +42,46 @@
|
|
30
42
|
|
31
43
|
|
32
44
|
|
45
|
+
HashSetの作成はO(n)ですが、検索はO(1)です。配列作成も内部がO(1)ならO(n)になりますので、計算量はO(n + m)とかなり改善されます。
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
###順序と重複を維持しない場合
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
順序を維持し、また、重複している場合は重複したままにする場合です。
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
####並び替え済みリストを使う
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
並び替え済みリストの場合、検索がO(1)と高速になります。C#には並び替え済みのSortedListがありますのでこれが使用できます。ただし、削除はO(n)であり、オリジナルより速い程度です。結局O(n × m)になってしまいます。
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
重複は維持されますが、順序はソートされるために維持できません。
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
####ハッシュ化された集合を使う
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
順序や重複を維持しなければいいのであれば、ハッシュ化された集合が使用できます。検索も削除もほぼO(1)になるため、極めて高速です。
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
ハッシュ化された集合としてHashSetが使用できます。なお、HashSetでは順序もそのまま維持されるようです(正式ドキュメントが見つけられなかったので、知っている人は教えて欲しい)。ただし、重複は維持されません。
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
ただし、ハッシュ化された集合自体の作成にO(n)必要になりますので、そこは注意してください。ということで、計算量はO(n + m)とかなり改善されます。。
|
82
|
+
|
83
|
+
|
84
|
+
|
33
85
|
###検証コード
|
34
86
|
|
35
87
|
|
@@ -112,11 +164,11 @@
|
|
112
164
|
|
113
165
|
deleteStopwatch.ElapsedMilliseconds);
|
114
166
|
|
115
|
-
|
116
|
-
|
167
|
+
|
168
|
+
|
117
|
-
|
169
|
+
Console.WriteLine();
|
118
|
-
|
119
|
-
|
170
|
+
|
171
|
+
|
120
172
|
|
121
173
|
List<string> list;
|
122
174
|
|
@@ -150,7 +202,7 @@
|
|
150
202
|
|
151
203
|
|
152
204
|
|
153
|
-
list =
|
205
|
+
list = CreateListWithHashset(new List<String>(mainList),
|
154
206
|
|
155
207
|
new List<String>(deleteList));
|
156
208
|
|
@@ -158,6 +210,34 @@
|
|
158
210
|
|
159
211
|
Console.WriteLine("最初: {0}", list[0]);
|
160
212
|
|
213
|
+
|
214
|
+
|
215
|
+
Console.WriteLine();
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
list = UseSortedList(new List<String>(mainList),
|
220
|
+
|
221
|
+
new List<String>(deleteList));
|
222
|
+
|
223
|
+
Console.WriteLine("サイズ: {0}", list.Count);
|
224
|
+
|
225
|
+
Console.WriteLine("最初: {0}", list[0]);
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
Console.WriteLine();
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
list = UseHashSet(new List<String>(mainList),
|
234
|
+
|
235
|
+
new List<String>(deleteList));
|
236
|
+
|
237
|
+
Console.WriteLine("サイズ: {0}", list.Count);
|
238
|
+
|
239
|
+
Console.WriteLine("最初: {0}", list[0]);
|
240
|
+
|
161
241
|
}
|
162
242
|
|
163
243
|
|
@@ -242,13 +322,15 @@
|
|
242
322
|
|
243
323
|
}
|
244
324
|
|
325
|
+
|
326
|
+
|
245
|
-
static List<String>
|
327
|
+
static List<String> CreateListWithHashset(List<String> mainList,
|
246
328
|
|
247
329
|
List<String> deleteList)
|
248
330
|
|
249
331
|
{
|
250
332
|
|
251
|
-
Console.WriteLine("start
|
333
|
+
Console.WriteLine("start CreateListWithHashset");
|
252
334
|
|
253
335
|
var runStopwatch = new Stopwatch();
|
254
336
|
|
@@ -276,6 +358,96 @@
|
|
276
358
|
|
277
359
|
}
|
278
360
|
|
361
|
+
|
362
|
+
|
363
|
+
static List<String> UseSortedList(List<String> mainList,
|
364
|
+
|
365
|
+
List<String> deleteList)
|
366
|
+
|
367
|
+
{
|
368
|
+
|
369
|
+
Console.WriteLine("start UseSortedList");
|
370
|
+
|
371
|
+
var runStopwatch = new Stopwatch();
|
372
|
+
|
373
|
+
runStopwatch.Start();
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
// SortedListに変換して処理をする。
|
378
|
+
|
379
|
+
var mainSortedList = new SortedList<String, String>(
|
380
|
+
|
381
|
+
mainList.ToDictionary(s => s));
|
382
|
+
|
383
|
+
foreach (string deleteStr in deleteList)
|
384
|
+
|
385
|
+
{
|
386
|
+
|
387
|
+
mainSortedList.Remove(deleteStr);
|
388
|
+
|
389
|
+
}
|
390
|
+
|
391
|
+
var newList = mainSortedList.Select(pair => pair.Value)
|
392
|
+
|
393
|
+
.ToList();
|
394
|
+
|
395
|
+
|
396
|
+
|
397
|
+
runStopwatch.Stop();
|
398
|
+
|
399
|
+
Console.WriteLine("run 完了: {0} ms",
|
400
|
+
|
401
|
+
runStopwatch.ElapsedMilliseconds);
|
402
|
+
|
403
|
+
return newList;
|
404
|
+
|
405
|
+
}
|
406
|
+
|
407
|
+
|
408
|
+
|
409
|
+
static List<String> UseHashSet(List<String> mainList,
|
410
|
+
|
411
|
+
List<String> deleteList)
|
412
|
+
|
413
|
+
{
|
414
|
+
|
415
|
+
Console.WriteLine("start UseHashSet");
|
416
|
+
|
417
|
+
var runStopwatch = new Stopwatch();
|
418
|
+
|
419
|
+
runStopwatch.Start();
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
// HashSetに変換して処理をする。
|
424
|
+
|
425
|
+
var mainHashSet = new HashSet<String>(mainList);
|
426
|
+
|
427
|
+
foreach (string deleteStr in deleteList)
|
428
|
+
|
429
|
+
{
|
430
|
+
|
431
|
+
mainHashSet.Remove(deleteStr);
|
432
|
+
|
433
|
+
}
|
434
|
+
|
435
|
+
var newList = mainHashSet.ToList();
|
436
|
+
|
437
|
+
|
438
|
+
|
439
|
+
runStopwatch.Stop();
|
440
|
+
|
441
|
+
Console.WriteLine("run 完了: {0} ms",
|
442
|
+
|
443
|
+
runStopwatch.ElapsedMilliseconds);
|
444
|
+
|
445
|
+
return newList;
|
446
|
+
|
447
|
+
}
|
448
|
+
|
449
|
+
|
450
|
+
|
279
451
|
}
|
280
452
|
|
281
453
|
```
|
@@ -294,38 +466,62 @@
|
|
294
466
|
|
295
467
|
60000個中5000個を削除
|
296
468
|
|
297
|
-
main 作成完了: 3
|
469
|
+
main 作成完了: 368 ms
|
298
|
-
|
470
|
+
|
299
|
-
delete 作成完了: 2
|
471
|
+
delete 作成完了: 26 ms
|
300
472
|
|
301
473
|
|
302
474
|
|
303
475
|
start Original
|
304
476
|
|
305
|
-
run 完了:
|
477
|
+
run 完了: 4572 ms
|
306
478
|
|
307
479
|
サイズ: 55000
|
308
480
|
|
309
|
-
最初: 5
|
481
|
+
最初: 57539
|
310
482
|
|
311
483
|
|
312
484
|
|
313
485
|
start UseLinkedList
|
314
486
|
|
315
|
-
run 完了: 28
|
487
|
+
run 完了: 3258 ms
|
316
488
|
|
317
489
|
サイズ: 55000
|
318
490
|
|
319
|
-
最初: 5
|
491
|
+
最初: 57539
|
320
|
-
|
321
|
-
|
322
|
-
|
492
|
+
|
493
|
+
|
494
|
+
|
323
|
-
start
|
495
|
+
start CreateListWithHashset
|
324
496
|
|
325
497
|
run 完了: 13 ms
|
326
498
|
|
327
499
|
サイズ: 55000
|
328
500
|
|
329
|
-
最初: 5
|
501
|
+
最初: 57539
|
502
|
+
|
503
|
+
|
504
|
+
|
505
|
+
start UseSortedList
|
506
|
+
|
507
|
+
run 完了: 2628 ms
|
508
|
+
|
509
|
+
サイズ: 55000
|
510
|
+
|
511
|
+
最初: 10000
|
512
|
+
|
513
|
+
|
514
|
+
|
515
|
+
start UseHashSet
|
516
|
+
|
517
|
+
run 完了: 16 ms
|
518
|
+
|
519
|
+
サイズ: 55000
|
520
|
+
|
521
|
+
最初: 57539
|
330
522
|
|
331
523
|
```
|
524
|
+
|
525
|
+
|
526
|
+
|
527
|
+
UseSortedListの最初の要素は異なります。UseHashSetの場合は重複が維持されないことに注意です。なお、順序づけしておきたい場合はSortedSetを使うという手段もあります。
|