Repository navigation
Expand file tree
/
Copy pathalgorithms.js
More file actions
1217 lines (1169 loc) · 53.4 KB
/
Copy pathalgorithms.js
File metadata and controls
1217 lines (1169 loc) · 53.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
const AlgorithmQuestions = {
sorts: [
{
id: 'sort_1',
title: '冒泡排序',
question: '冒泡排序的平均时间复杂度是多少?',
options: ['O(n)', 'O(n log n)', 'O(n²)', 'O(log n)'],
correct: 2,
explanation: '冒泡排序需要两层嵌套循环,外层循环执行n次,内层循环平均执行n/2次,所以时间复杂度为O(n²)',
visualization: 'bubbleSort'
},
{
id: 'sort_2',
title: '快速排序',
question: '快速排序在最坏情况下的时间复杂度是多少?',
options: ['O(n)', 'O(n log n)', 'O(n²)', 'O(log n)'],
correct: 2,
explanation: '当数组已经有序或逆序时,快速排序的分区会极度不平衡,导致最坏时间复杂度为O(n²)',
visualization: 'quickSort'
},
{
id: 'sort_3',
title: '归并排序',
question: '归并排序的空间复杂度是多少?',
options: ['O(1)', 'O(log n)', 'O(n)', 'O(n²)'],
correct: 2,
explanation: '归并排序需要额外的O(n)空间来存储临时数组',
visualization: 'mergeSort'
},
{
id: 'sort_4',
title: '堆排序',
question: '堆排序是基于什么数据结构实现的?',
options: ['栈', '队列', '二叉堆', '链表'],
correct: 2,
explanation: '堆排序利用二叉堆的性质进行排序,通过建堆和调整堆来完成排序过程',
visualization: 'heapSort'
},
{
id: 'sort_5',
title: '插入排序',
question: '插入排序在最好情况下的时间复杂度是多少?',
options: ['O(1)', 'O(n)', 'O(n log n)', 'O(n²)'],
correct: 1,
explanation: '当数组已经有序时,插入排序只需要遍历一次数组,时间复杂度为O(n)',
visualization: 'insertionSort'
},
{
id: 'sort_6',
title: '选择排序',
question: '选择排序是稳定排序吗?',
options: ['是', '否', '取决于数据', '不确定'],
correct: 1,
explanation: '选择排序是不稳定排序,因为在交换时可能改变相等元素的相对位置',
visualization: 'selectionSort'
},
{
id: 'sort_7',
title: '计数排序',
question: '计数排序适用于什么类型的数据?',
options: ['任意数据', '浮点数', '整数', '字符串'],
correct: 2,
explanation: '计数排序需要知道数据的范围,适用于整数或可以映射到整数的数据',
visualization: 'countingSort'
},
{
id: 'sort_8',
title: '基数排序',
question: '基数排序的时间复杂度是多少?',
options: ['O(n)', 'O(nk)', 'O(n log n)', 'O(n²)'],
correct: 1,
explanation: '基数排序的时间复杂度为O(nk),其中n是元素个数,k是数字的最大位数',
visualization: 'radixSort'
}
],
search: [
{
id: 'search_1',
title: '二分搜索',
question: '二分搜索的前提条件是什么?',
options: ['数组无序', '数组有序', '数组长度为偶数', '数组元素唯一'],
correct: 1,
explanation: '二分搜索要求数组必须是有序的,否则无法确定搜索方向',
visualization: 'binarySearch'
},
{
id: 'search_2',
title: '线性搜索',
question: '线性搜索的时间复杂度是多少?',
options: ['O(1)', 'O(log n)', 'O(n)', 'O(n²)'],
correct: 2,
explanation: '线性搜索需要逐个检查每个元素,最坏情况下需要检查所有n个元素',
visualization: 'linearSearch'
},
{
id: 'search_3',
title: '二分搜索',
question: '二分搜索的时间复杂度是多少?',
options: ['O(1)', 'O(log n)', 'O(n)', 'O(n log n)'],
correct: 1,
explanation: '每次搜索都将搜索范围缩小一半,所以时间复杂度为O(log n)',
visualization: 'binarySearch'
},
{
id: 'search_4',
title: '深度优先搜索',
question: 'DFS通常使用什么数据结构实现?',
options: ['队列', '栈', '堆', '链表'],
correct: 1,
explanation: 'DFS使用栈来保存待访问的节点,实现后进先出的访问顺序',
visualization: 'dfs'
},
{
id: 'search_5',
title: '广度优先搜索',
question: 'BFS通常使用什么数据结构实现?',
options: ['队列', '栈', '堆', '链表'],
correct: 0,
explanation: 'BFS使用队列来保存待访问的节点,实现先进先出的访问顺序',
visualization: 'bfs'
}
],
graphs: [
{
id: 'graph_1',
title: 'Dijkstra算法',
question: 'Dijkstra算法用于解决什么问题?',
options: ['最小生成树', '单源最短路径', '拓扑排序', '最大流'],
correct: 1,
explanation: 'Dijkstra算法用于求解带权图中单源点到其他所有点的最短路径',
visualization: 'dijkstra'
},
{
id: 'graph_2',
title: 'Kruskal算法',
question: 'Kruskal算法用于解决什么问题?',
options: ['最短路径', '最小生成树', '拓扑排序', '二分图检测'],
correct: 1,
explanation: 'Kruskal算法是一种贪心算法,用于求解最小生成树问题',
visualization: 'kruskal'
},
{
id: 'graph_3',
title: '拓扑排序',
question: '拓扑排序适用于什么类型的图?',
options: ['无向图', '有向无环图', '完全图', '二分图'],
correct: 1,
explanation: '拓扑排序只能应用于有向无环图(DAG),用于确定任务的执行顺序',
visualization: 'topologicalSort'
},
{
id: 'graph_4',
title: 'Floyd-Warshall算法',
question: 'Floyd-Warshall算法的时间复杂度是多少?',
options: ['O(n)', 'O(n²)', 'O(n³)', 'O(n log n)'],
correct: 2,
explanation: 'Floyd-Warshall算法使用三重循环,时间复杂度为O(n³)',
visualization: 'floydWarshall'
},
{
id: 'graph_5',
title: '连通分量',
question: '一个无向图有3个连通分量意味着什么?',
options: ['图有3个节点', '图有3条边', '图被分成3个互不相连的部分', '图有3个环'],
correct: 2,
explanation: '连通分量是图中最大的连通子图,3个连通分量意味着图被分成3个独立的部分',
visualization: 'connectedComponents'
},
{
id: 'graph_6',
title: 'Bellman-Ford算法',
question: 'Bellman-Ford算法相比Dijkstra算法的优势是什么?',
options: ['更快', '可以处理负权边', '空间更少', '代码更简单'],
correct: 1,
explanation: 'Bellman-Ford算法可以处理带有负权边的图,而Dijkstra算法不能',
visualization: 'bellmanFord'
}
],
trees: [
{
id: 'tree_1',
title: '二叉搜索树',
question: '二叉搜索树的查找操作平均时间复杂度是多少?',
options: ['O(1)', 'O(log n)', 'O(n)', 'O(n log n)'],
correct: 1,
explanation: '在平衡的二叉搜索树中,查找操作平均时间复杂度为O(log n)',
visualization: 'bstSearch'
},
{
id: 'tree_2',
title: 'AVL树',
question: 'AVL树是什么类型的树?',
options: ['完全二叉树', '满二叉树', '自平衡二叉搜索树', 'B树'],
correct: 2,
explanation: 'AVL树是一种自平衡二叉搜索树,任何节点的两个子树高度差不超过1',
visualization: 'avlTree'
},
{
id: 'tree_3',
title: '树的遍历',
question: '中序遍历二叉搜索树的结果是什么?',
options: ['降序序列', '升序序列', '无序序列', '随机序列'],
correct: 1,
explanation: '中序遍历二叉搜索树会得到升序排列的节点值序列',
visualization: 'inorderTraversal'
},
{
id: 'tree_4',
title: '字典树(Trie)',
question: 'Trie主要用于什么操作?',
options: ['数值计算', '字符串查找', '图像处理', '音频分析'],
correct: 1,
explanation: 'Trie树主要用于字符串的快速查找、前缀匹配等操作',
visualization: 'trie'
},
{
id: 'tree_5',
title: '堆',
question: '最大堆的根节点有什么特性?',
options: ['是最小值', '是最大值', '是中位数', '是平均值'],
correct: 1,
explanation: '最大堆中,根节点是整个堆中的最大值',
visualization: 'maxHeap'
},
{
id: 'tree_6',
title: '线段树',
question: '线段树主要用于解决什么问题?',
options: ['字符串匹配', '区间查询和更新', '图的最短路径', '排序问题'],
correct: 1,
explanation: '线段树用于高效处理区间查询和区间更新问题',
visualization: 'segmentTree'
}
],
dp: [
{
id: 'dp_1',
title: '斐波那契数列',
question: '使用动态规划计算斐波那契数列的时间复杂度是多少?',
options: ['O(1)', 'O(n)', 'O(n²)', 'O(2^n)'],
correct: 1,
explanation: '动态规划通过存储中间结果,将时间复杂度从递归的O(2^n)优化到O(n)',
visualization: 'fibonacci'
},
{
id: 'dp_2',
title: '背包问题',
question: '0-1背包问题中,每个物品可以取几次?',
options: ['0次', '1次', '无限次', '任意次'],
correct: 1,
explanation: '0-1背包问题中,每个物品最多只能取一次(要么取,要么不取)',
visualization: 'knapsack'
},
{
id: 'dp_3',
title: '最长公共子序列',
question: 'LCS问题的时间复杂度是多少?',
options: ['O(n)', 'O(m+n)', 'O(mn)', 'O(m²n²)'],
correct: 2,
explanation: 'LCS需要填充一个m×n的表格,时间复杂度为O(mn)',
visualization: 'lcs'
},
{
id: 'dp_4',
title: '最长递增子序列',
question: 'LIS问题的最优时间复杂度是多少?',
options: ['O(n)', 'O(n log n)', 'O(n²)', 'O(log n)'],
correct: 1,
explanation: '使用二分查找优化的LIS算法可以达到O(n log n)的时间复杂度',
visualization: 'lis'
},
{
id: 'dp_5',
title: '编辑距离',
question: '编辑距离问题中,允许的操作有哪些?',
options: ['只有插入', '只有删除', '插入、删除、替换', '只有替换'],
correct: 2,
explanation: '编辑距离允许三种操作:插入一个字符、删除一个字符、替换一个字符',
visualization: 'editDistance'
},
{
id: 'dp_6',
title: '爬楼梯',
question: '爬楼梯问题:每次可以爬1或2阶,n阶楼梯有多少种方法?',
options: ['n种', '2^n种', '斐波那契数', 'n!种'],
correct: 2,
explanation: '爬楼梯问题的解就是斐波那契数列,f(n) = f(n-1) + f(n-2)',
visualization: 'climbingStairs'
}
],
backtracking: [
{
id: 'back_1',
title: 'N皇后问题',
question: 'N皇后问题中,8皇后问题有多少种解?',
options: ['8种', '64种', '92种', '40320种'],
correct: 2,
explanation: '8皇后问题共有92种不同的解法',
visualization: 'nQueens'
},
{
id: 'back_2',
title: '全排列',
question: 'n个不同元素的全排列有多少种?',
options: ['n种', '2^n种', 'n!种', 'n²种'],
correct: 2,
explanation: 'n个不同元素的全排列数为n!(n的阶乘)',
visualization: 'permutations'
},
{
id: 'back_3',
title: '子集生成',
question: 'n个元素的集合有多少个子集?',
options: ['n个', 'n!个', '2^n个', '2n个'],
correct: 2,
explanation: '每个元素都有选或不选两种可能,所以共有2^n个子集',
visualization: 'subsets'
},
{
id: 'back_4',
title: '数独求解',
question: '标准数独的网格大小是多少?',
options: ['6×6', '8×8', '9×9', '10×10'],
correct: 2,
explanation: '标准数独是9×9的网格,分为9个3×3的小格子',
visualization: 'sudoku'
},
{
id: 'back_5',
title: '括号生成',
question: 'n对括号可以生成多少种有效的括号组合?',
options: ['n种', '2^n种', '卡特兰数C_n', 'n!种'],
correct: 2,
explanation: 'n对括号的有效组合数等于第n个卡特兰数',
visualization: 'parentheses'
}
],
bitmanipulation: [
{
id: 'bit_1',
title: '位运算',
question: '判断一个数是否为2的幂,可以使用什么位运算?',
options: ['n & (n-1) == 0', 'n | (n-1) == n', 'n ^ n == 0', 'n << 1 == 0'],
correct: 0,
explanation: '如果n是2的幂,则n的二进制只有一个1,n & (n-1)会将这个1变为0',
visualization: 'powerOfTwo'
},
{
id: 'bit_2',
title: '异或运算',
question: '异或运算(XOR)有什么特性?',
options: ['a ^ a = 1', 'a ^ 0 = 0', 'a ^ a = 0', 'a ^ 1 = a'],
correct: 2,
explanation: '异或运算满足:a ^ a = 0,a ^ 0 = a,这是异或的重要性质',
visualization: 'xorOperation'
},
{
id: 'bit_3',
title: '位计数',
question: '计算一个整数中1的个数,最优算法的时间复杂度是?',
options: ['O(n)', 'O(log n)', 'O(1)', 'O(位数中1的个数)'],
correct: 3,
explanation: 'Brian Kernighan算法每次消除最右边的1,时间复杂度为O(1的个数)',
visualization: 'countBits'
},
{
id: 'bit_4',
title: '位运算交换',
question: '如何用位运算交换两个数(不使用临时变量)?',
options: ['a=a^b; b=a^b; a=a^b', 'a=a|b; b=a|b; a=a|b', 'a=a&b; b=a&b; a=a&b', 'a=~a; b=~b'],
correct: 0,
explanation: '利用异或的性质:a^b^b = a,可以通过三次异或完成交换',
visualization: 'swapBits'
},
{
id: 'bit_5',
title: '格雷码',
question: '格雷码的特点是什么?',
options: ['相邻数差1', '相邻数只有一位不同', '所有数都是偶数', '所有数都是奇数'],
correct: 1,
explanation: '格雷码是一种二进制编码,相邻的两个数只有一位不同',
visualization: 'grayCode'
}
],
strings: [
{
id: 'str_1',
title: 'KMP算法',
question: 'KMP算法用于解决什么问题?',
options: ['字符串排序', '字符串匹配', '字符串压缩', '字符串加密'],
correct: 1,
explanation: 'KMP算法是一种高效的字符串匹配算法,时间复杂度为O(n+m)',
visualization: 'kmp'
},
{
id: 'str_2',
title: '回文判断',
question: '判断回文字符串的时间复杂度最低可以是?',
options: ['O(n)', 'O(n log n)', 'O(n²)', 'O(1)'],
correct: 0,
explanation: '使用双指针法,从两端向中间比较,时间复杂度为O(n)',
visualization: 'palindrome'
},
{
id: 'str_3',
title: '最长无重复子串',
question: '求最长无重复字符子串的最优时间复杂度是?',
options: ['O(n)', 'O(n log n)', 'O(n²)', 'O(2^n)'],
correct: 0,
explanation: '使用滑动窗口法,配合哈希表,可以在O(n)时间内解决',
visualization: 'longestSubstring'
},
{
id: 'str_4',
title: '字符串哈希',
question: '字符串哈希的主要用途是什么?',
options: ['加密', '快速比较字符串', '压缩', '排序'],
correct: 1,
explanation: '字符串哈希可以将字符串映射为数值,实现O(1)时间的字符串比较',
visualization: 'stringHash'
},
{
id: 'str_5',
title: '编辑距离',
question: '两个字符串的编辑距离是指?',
options: ['字符差异数', '长度差', '最小编辑操作数', '公共字符数'],
correct: 2,
explanation: '编辑距离是将一个字符串转换为另一个字符串所需的最少编辑操作次数',
visualization: 'editDistance'
},
{
id: 'str_6',
title: 'Boyer-Moore算法',
question: 'Boyer-Moore算法的特点是什么?',
options: ['从左向右匹配', '从右向左匹配', '随机匹配', '分治匹配'],
correct: 1,
explanation: 'Boyer-Moore算法从右向左匹配,利用坏字符规则实现高效跳跃',
visualization: 'boyerMoore'
}
]
};
const Visualizations = {
bubbleSort(container) {
const arr = [64, 34, 25, 12, 22, 11, 90];
const maxVal = Math.max(...arr);
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${i < 2 ? 'comparing' : ''}" style="height: ${(v / maxVal) * 150}px">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">冒泡排序:相邻元素两两比较</p>
`;
container.innerHTML = html;
},
quickSort(container) {
const arr = [10, 7, 8, 9, 1, 5];
const maxVal = Math.max(...arr);
const pivotIndex = 3;
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${i === pivotIndex ? 'pivot' : ''}" style="height: ${(v / maxVal) * 150}px">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #f368e0;">快速排序:选择基准元素分区</p>
`;
container.innerHTML = html;
},
mergeSort(container) {
const arr = [38, 27, 43, 3, 9, 82, 10];
const maxVal = Math.max(...arr);
const html = `
<div class="array-container">
${arr.map(v => `
<div class="array-bar" style="height: ${(v / maxVal) * 150}px">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">归并排序:分治法,先分后合</p>
`;
container.innerHTML = html;
},
heapSort(container) {
const arr = [4, 10, 3, 5, 1];
const html = `
<div style="text-align: center;">
<div style="font-size: 2rem; margin-bottom: 20px;">🌳</div>
<div class="array-container">
${arr.map(v => `<div class="array-bar sorted" style="height: ${v * 20}px">${v}</div>`).join('')}
</div>
<p style="margin-top: 15px; color: #1dd1a1;">堆结构:完全二叉树,父节点大于子节点</p>
</div>
`;
container.innerHTML = html;
},
insertionSort(container) {
const arr = [12, 11, 13, 5, 6];
const maxVal = Math.max(...arr);
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${i === 1 ? 'comparing' : ''}" style="height: ${(v / maxVal) * 150}px">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">插入排序:将元素插入已排序部分</p>
`;
container.innerHTML = html;
},
selectionSort(container) {
const arr = [64, 25, 12, 22, 11];
const maxVal = Math.max(...arr);
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${i === 4 ? 'sorted' : ''}" style="height: ${(v / maxVal) * 150}px">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #1dd1a1;">选择排序:每轮选出最小元素</p>
`;
container.innerHTML = html;
},
countingSort(container) {
const arr = [1, 4, 1, 2, 7, 5, 2];
const count = [0, 2, 2, 0, 1, 1, 0, 1];
const html = `
<div style="text-align: center;">
<p>原数组: [${arr.join(', ')}]</p>
<div style="margin: 20px 0;">
<p>计数数组:</p>
<div class="array-container">
${count.map((c, i) => `<div class="array-bar" style="height: ${c * 40 + 20}px; width: 30px;">${i}:${c}</div>`).join('')}
</div>
</div>
<p style="color: #00d4ff;">计数排序:统计每个元素出现次数</p>
</div>
`;
container.innerHTML = html;
},
radixSort(container) {
const arr = [170, 45, 75, 90, 802, 24, 2, 66];
const html = `
<div style="text-align: center;">
<p>按位排序过程:</p>
<div class="array-container" style="flex-wrap: wrap; gap: 10px;">
${arr.map(v => `<div class="array-bar" style="height: 40px; width: 50px;">${v}</div>`).join('')}
</div>
<p style="margin-top: 15px; color: #00d4ff;">基数排序:从低位到高位依次排序</p>
</div>
`;
container.innerHTML = html;
},
binarySearch(container) {
const arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91];
const target = 23;
const mid = 5;
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${i === mid ? 'pivot' : ''} ${v === target ? 'sorted' : ''}" style="height: 60px; width: 45px;">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #f368e0;">目标: ${target},中间位置: ${mid}</p>
`;
container.innerHTML = html;
},
linearSearch(container) {
const arr = [64, 34, 25, 12, 22, 11, 90];
const target = 22;
const html = `
<div class="array-container">
${arr.map((v, i) => `
<div class="array-bar ${v === target ? 'sorted' : (i < 4 ? 'comparing' : '')}" style="height: 60px; width: 45px;">
${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #1dd1a1;">线性搜索:逐个查找目标 ${target}</p>
`;
container.innerHTML = html;
},
dfs(container) {
const html = `
<div class="graph-container" style="height: 200px; position: relative;">
<div class="graph-node current" style="left: 50%; top: 10px;">A</div>
<div class="graph-node visited" style="left: 25%; top: 80px;">B</div>
<div class="graph-node" style="left: 75%; top: 80px;">C</div>
<div class="graph-node" style="left: 10%; top: 150px;">D</div>
<div class="graph-node visited" style="left: 40%; top: 150px;">E</div>
<div class="graph-node" style="left: 70%; top: 150px;">F</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">DFS:深度优先,一条路走到底</p>
`;
container.innerHTML = html;
},
bfs(container) {
const html = `
<div class="graph-container" style="height: 200px; position: relative;">
<div class="graph-node current" style="left: 50%; top: 10px;">A</div>
<div class="graph-node visited" style="left: 25%; top: 80px;">B</div>
<div class="graph-node visited" style="left: 75%; top: 80px;">C</div>
<div class="graph-node" style="left: 10%; top: 150px;">D</div>
<div class="graph-node" style="left: 40%; top: 150px;">E</div>
<div class="graph-node" style="left: 70%; top: 150px;">F</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">BFS:广度优先,逐层遍历</p>
`;
container.innerHTML = html;
},
dijkstra(container) {
const html = `
<div class="graph-container" style="height: 200px; position: relative;">
<div class="graph-node visited" style="left: 10%; top: 80px;">0</div>
<div class="graph-node current" style="left: 35%; top: 30px;">1</div>
<div class="graph-node visited" style="left: 35%; top: 130px;">2</div>
<div class="graph-node" style="left: 60%; top: 80px;">3</div>
<div class="graph-node" style="left: 85%; top: 80px;">4</div>
<div style="position: absolute; left: 15%; top: 50px; color: #1dd1a1; font-size: 12px;">dist=0</div>
<div style="position: absolute; left: 40%; top: 5px; color: #feca57; font-size: 12px;">dist=4</div>
<div style="position: absolute; left: 40%; top: 155px; color: #1dd1a1; font-size: 12px;">dist=2</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">Dijkstra:从起点计算最短路径</p>
`;
container.innerHTML = html;
},
kruskal(container) {
const html = `
<div style="text-align: center;">
<p>边按权重排序: (1,2)=1, (2,3)=2, (0,1)=3...</p>
<div class="graph-container" style="height: 150px; position: relative;">
<div class="graph-node visited" style="left: 20%; top: 50px;">0</div>
<div class="graph-node visited" style="left: 40%; top: 50px;">1</div>
<div class="graph-node visited" style="left: 60%; top: 50px;">2</div>
<div class="graph-node visited" style="left: 80%; top: 50px;">3</div>
</div>
<p style="color: #1dd1a1;">Kruskal:按边权重从小到大选择</p>
</div>
`;
container.innerHTML = html;
},
topologicalSort(container) {
const html = `
<div style="text-align: center;">
<p>任务依赖关系:</p>
<div class="array-container" style="margin-top: 20px;">
${['A', 'B', 'C', 'D', 'E'].map((v, i) => `
<div class="array-bar sorted" style="height: 50px; width: 50px;">${v}</div>
`).join('')}
</div>
<p style="margin-top: 15px; color: #00d4ff;">拓扑排序:按依赖关系排序任务</p>
</div>
`;
container.innerHTML = html;
},
floydWarshall(container) {
const html = `
<div style="text-align: center;">
<p>距离矩阵:</p>
<div style="display: grid; grid-template-columns: repeat(4, 50px); gap: 5px; justify-content: center; margin: 20px 0;">
<div class="array-bar" style="height: 30px; width: 40px;">∞</div>
<div class="array-bar" style="height: 30px; width: 40px;">3</div>
<div class="array-bar" style="height: 30px; width: 40px;">∞</div>
<div class="array-bar" style="height: 30px; width: 40px;">5</div>
</div>
<p style="color: #00d4ff;">Floyd-Warshall:计算所有点对最短路径</p>
</div>
`;
container.innerHTML = html;
},
connectedComponents(container) {
const html = `
<div class="graph-container" style="height: 180px; position: relative;">
<div class="graph-node visited" style="left: 10%; top: 50px;">1</div>
<div class="graph-node visited" style="left: 25%; top: 100px;">2</div>
<div class="graph-node current" style="left: 50%; top: 50px;">3</div>
<div class="graph-node current" style="left: 65%; top: 100px;">4</div>
<div class="graph-node" style="left: 85%; top: 70px;">5</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">连通分量:3个独立的连通区域</p>
`;
container.innerHTML = html;
},
bellmanFord(container) {
const html = `
<div style="text-align: center;">
<p>支持负权边的最短路径算法</p>
<div class="graph-container" style="height: 150px; position: relative;">
<div class="graph-node visited" style="left: 20%; top: 50px;">0</div>
<div class="graph-node current" style="left: 50%; top: 50px;">1</div>
<div class="graph-node" style="left: 80%; top: 50px;">2</div>
</div>
<p style="color: #feca57;">边: (0→1, -2), (1→2, 3)</p>
</div>
`;
container.innerHTML = html;
},
bstSearch(container) {
const html = `
<div class="tree-container" style="height: 200px; position: relative;">
<div class="tree-node" style="left: 50%; top: 10px;">8</div>
<div class="tree-node highlighted" style="left: 25%; top: 70px;">3</div>
<div class="tree-node" style="left: 75%; top: 70px;">10</div>
<div class="tree-node" style="left: 10%; top: 130px;">1</div>
<div class="tree-node" style="left: 40%; top: 130px;">6</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #feca57;">BST搜索:比节点小向左,大向右</p>
`;
container.innerHTML = html;
},
avlTree(container) {
const html = `
<div class="tree-container" style="height: 200px; position: relative;">
<div class="tree-node" style="left: 50%; top: 10px;">8</div>
<div class="tree-node" style="left: 30%; top: 70px;">4</div>
<div class="tree-node" style="left: 70%; top: 70px;">12</div>
<div class="tree-node" style="left: 15%; top: 130px;">2</div>
<div class="tree-node" style="left: 45%; top: 130px;">6</div>
<div class="tree-node" style="left: 60%; top: 130px;">10</div>
<div class="tree-node" style="left: 85%; top: 130px;">14</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">AVL树:自动平衡,高度差≤1</p>
`;
container.innerHTML = html;
},
inorderTraversal(container) {
const html = `
<div class="tree-container" style="height: 200px; position: relative;">
<div class="tree-node" style="left: 50%; top: 10px;">4</div>
<div class="tree-node visited" style="left: 25%; top: 70px;">2</div>
<div class="tree-node" style="left: 75%; top: 70px;">6</div>
<div class="tree-node visited" style="left: 10%; top: 130px;">1</div>
<div class="tree-node visited" style="left: 40%; top: 130px;">3</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #1dd1a1;">中序遍历: 1→2→3→4→6 (升序)</p>
`;
container.innerHTML = html;
},
trie(container) {
const html = `
<div style="text-align: center;">
<p>字典树存储: "cat", "car", "dog"</p>
<div style="display: flex; justify-content: center; gap: 50px; margin: 30px 0;">
<div style="display: flex; flex-direction: column; align-items: center;">
<div class="tree-node" style="position: relative;">c</div>
<div style="display: flex; gap: 20px; margin-top: 20px;">
<div class="tree-node" style="position: relative;">a</div>
</div>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<div class="tree-node sorted" style="position: relative;">t</div>
<div class="tree-node sorted" style="position: relative;">r</div>
</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center;">
<div class="tree-node" style="position: relative;">d</div>
<div style="margin-top: 20px;">
<div class="tree-node" style="position: relative;">o</div>
</div>
<div style="margin-top: 20px;">
<div class="tree-node sorted" style="position: relative;">g</div>
</div>
</div>
</div>
</div>
`;
container.innerHTML = html;
},
maxHeap(container) {
const html = `
<div class="tree-container" style="height: 200px; position: relative;">
<div class="tree-node highlighted" style="left: 50%; top: 10px;">9</div>
<div class="tree-node" style="left: 30%; top: 70px;">7</div>
<div class="tree-node" style="left: 70%; top: 70px;">8</div>
<div class="tree-node" style="left: 15%; top: 130px;">5</div>
<div class="tree-node" style="left: 45%; top: 130px;">6</div>
</div>
<p style="text-align: center; margin-top: 15px; color: #feca57;">最大堆:根节点是最大值</p>
`;
container.innerHTML = html;
},
segmentTree(container) {
const html = `
<div style="text-align: center;">
<p>原数组: [1, 3, 5, 7, 9, 11]</p>
<p>线段树存储区间和:</p>
<div class="tree-container" style="height: 180px; position: relative;">
<div class="tree-node" style="left: 50%; top: 10px; font-size: 12px;">36</div>
<div class="tree-node" style="left: 25%; top: 70px; font-size: 12px;">16</div>
<div class="tree-node" style="left: 75%; top: 70px; font-size: 12px;">20</div>
<div class="tree-node" style="left: 12%; top: 130px; font-size: 10px;">4</div>
<div class="tree-node" style="left: 37%; top: 130px; font-size: 10px;">12</div>
<div class="tree-node" style="left: 62%; top: 130px; font-size: 10px;">16</div>
<div class="tree-node" style="left: 87%; top: 130px; font-size: 10px;">4</div>
</div>
</div>
`;
container.innerHTML = html;
},
fibonacci(container) {
const fib = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
const html = `
<div class="array-container">
${fib.map((v, i) => `
<div class="array-bar ${i >= 5 ? 'sorted' : ''}" style="height: ${v * 4 + 20}px; width: 45px;">
F${i}=${v}
</div>
`).join('')}
</div>
<p style="text-align: center; margin-top: 15px; color: #00d4ff;">F(n) = F(n-1) + F(n-2)</p>
`;
container.innerHTML = html;
},
knapsack(container) {
const html = `
<div style="text-align: center;">
<p>物品: 重量[2,3,4,5] 价值[3,4,5,6] 背包容量: 8</p>
<div style="display: grid; grid-template-columns: repeat(5, 50px); gap: 5px; justify-content: center; margin: 20px 0;">
<div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 5px;">容量\\物品</div>
<div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 5px;">0</div>
<div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 5px;">1</div>
<div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 5px;">2</div>
<div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 5px;">3</div>
<div style="background: rgba(0,212,255,0.3); padding: 10px; border-radius: 5px;">0</div>
<div style="background: rgba(0,212,255,0.1); padding: 10px; border-radius: 5px;">0</div>
<div style="background: rgba(0,212,255,0.1); padding: 10px; border-radius: 5px;">0</div>
<div style="background: rgba(0,212,255,0.1); padding: 10px; border-radius: 5px;">0</div>
<div style="background: rgba(0,212,255,0.1); padding: 10px; border-radius: 5px;">0</div>
</div>
<p style="color: #00d4ff;">DP表格:dp[i][w]表示前i个物品容量w的最大价值</p>
</div>
`;
container.innerHTML = html;
},
lcs(container) {
const html = `
<div style="text-align: center;">
<p>字符串: "ABCDGH" 和 "AEDFHR"</p>
<p style="color: #1dd1a1; margin: 20px 0;">最长公共子序列: "ADH" (长度=3)</p>
<div class="string-display">
${'ABCDGH'.split('').map((c, i) => `
<div class="char-box ${['A', 'D', 'H'].includes(c) ? 'match' : ''}">${c}</div>
`).join('')}
</div>
</div>
`;
container.innerHTML = html;
},
lis(container) {
const arr = [10, 22, 9, 33, 21, 50, 41, 60];
const lis = [10, 22, 33, 50, 60];
const html = `
<div style="text-align: center;">
<p>数组: [${arr.join(', ')}]</p>
<div class="array-container" style="margin: 20px 0;">
${arr.map(v => `
<div class="array-bar ${lis.includes(v) ? 'sorted' : ''}" style="height: ${v}px; width: 35px;">
${v}
</div>
`).join('')}
</div>
<p style="color: #1dd1a1;">最长递增子序列长度: 5</p>
</div>
`;
container.innerHTML = html;
},
editDistance(container) {
const html = `
<div style="text-align: center;">
<p>"kitten" → "sitting"</p>
<div style="display: flex; justify-content: center; gap: 20px; margin: 20px 0;">
<div class="string-display">
${'kitten'.split('').map((c, i) => `
<div class="char-box ${i === 0 ? 'highlight' : ''}">${c}</div>
`).join('')}
</div>
<span style="font-size: 1.5rem;">→</span>
<div class="string-display">
${'sitting'.split('').map((c, i) => `
<div class="char-box ${i === 0 ? 'highlight' : ''}">${c}</div>
`).join('')}
</div>
</div>
<p style="color: #00d4ff;">编辑距离: 3 (替换k→s, 替换e→i, 插入g)</p>
</div>
`;
container.innerHTML = html;
},
climbingStairs(container) {
const html = `
<div style="text-align: center;">
<div style="display: flex; justify-content: center; gap: 5px; margin: 20px 0;">
${[1,2,3,4,5,6].map(i => `
<div style="width: 50px; height: ${i * 25}px; background: linear-gradient(180deg, #00d4ff, #7b2cbf); display: flex; justify-content: center; align-items: center; color: white; font-weight: bold;">${i}</div>
`).join('')}
</div>
<p style="color: #00d4ff;">n阶楼梯的方法数 = F(n)</p>
<p style="color: #1dd1a1;">f(6) = f(5) + f(4) = 8 + 5 = 13种方法</p>
</div>
`;
container.innerHTML = html;
},
nQueens(container) {
const board = [
[0,0,1,0],
[1,0,0,0],
[0,0,0,1],
[0,1,0,0]
];
const html = `
<div style="text-align: center;">
<p>4皇后问题的一个解:</p>
<div style="display: grid; grid-template-columns: repeat(4, 40px); gap: 2px; justify-content: center; margin: 20px 0;">
${board.flat().map(cell => `
<div style="width: 40px; height: 40px; background: ${cell ? 'linear-gradient(145deg, #feca57, #ff6b6b)' : 'rgba(255,255,255,0.1)'}; border-radius: 5px; display: flex; justify-content: center; align-items: center;">
${cell ? '♛' : ''}
</div>
`).join('')}
</div>
<p style="color: #00d4ff;">每行、每列、每条对角线只能有一个皇后</p>
</div>
`;
container.innerHTML = html;
},
permutations(container) {
const html = `
<div style="text-align: center;">
<p>[1, 2, 3]的全排列:</p>
<div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 20px 0;">
${[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]].map(p => `
<div style="background: rgba(0,212,255,0.2); padding: 10px 15px; border-radius: 8px; border: 1px solid #00d4ff;">
[${p.join(', ')}]
</div>
`).join('')}
</div>
<p style="color: #00d4ff;">共 3! = 6 种排列</p>
</div>
`;
container.innerHTML = html;
},
subsets(container) {
const html = `
<div style="text-align: center;">
<p>[1, 2]的所有子集:</p>
<div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 20px 0;">
${['[]', '[1]', '[2]', '[1,2]'].map(s => `
<div style="background: rgba(0,212,255,0.2); padding: 10px 15px; border-radius: 8px; border: 1px solid #00d4ff;">
${s}
</div>
`).join('')}
</div>
<p style="color: #00d4ff;">共 2² = 4 个子集</p>
</div>
`;
container.innerHTML = html;
},
sudoku(container) {