随机打乱数组的方法与算法优化思路
随机打乱数组的方法与算法优化思路
方法1
构造一个空的数组1,把输入数组中的数按顺序随机放入到数组1的空位中。
1 | #!/usr/bin/python3 |
输出:1
2
3
4
5
6
7
8
9
10
11
12array_rand1:
[None, None, None, None, None, None, None, 1, None, None]
[None, None, None, None, None, None, 2, 1, None, None]
[None, None, None, None, None, None, 2, 1, None, 3]
[4, None, None, None, None, None, 2, 1, None, 3]
[4, None, None, None, 5, None, 2, 1, None, 3]
[4, None, None, None, 5, None, 2, 1, 6, 3]
[4, None, None, 7, 5, None, 2, 1, 6, 3]
[4, 8, None, 7, 5, None, 2, 1, 6, 3]
[4, 8, 9, 7, 5, None, 2, 1, 6, 3]
[4, 8, 9, 7, 5, 10, 2, 1, 6, 3]
打乱结果:[4, 8, 9, 7, 5, 10, 2, 1, 6, 3]
方法2
对方法1进行优化
有序抽取随放入修改为随机抽取有序放入
1 | #!/usr/bin/python3 |
输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22array_rand2:
[6]
[1, 2, 3, 4, 5, 7, 8, 9, 10]
[6, 9]
[1, 2, 3, 4, 5, 7, 8, 10]
[6, 9, 3]
[1, 2, 4, 5, 7, 8, 10]
[6, 9, 3, 2]
[1, 4, 5, 7, 8, 10]
[6, 9, 3, 2, 1]
[4, 5, 7, 8, 10]
[6, 9, 3, 2, 1, 4]
[5, 7, 8, 10]
[6, 9, 3, 2, 1, 4, 8]
[5, 7, 10]
[6, 9, 3, 2, 1, 4, 8, 5]
[7, 10]
[6, 9, 3, 2, 1, 4, 8, 5, 7]
[10]
[6, 9, 3, 2, 1, 4, 8, 5, 7, 10]
[]
打乱结果:[6, 9, 3, 2, 1, 4, 8, 5, 7, 10]
方法3
对方法2进行优化
方法2中从arr2抽取放入arr1中,arr1和arr2元素总数等于输入的数组。
考虑把乱序后的数组放前面,未乱序的数据放数组后面。可以节约1个arr1的内存。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random
def array_rand3(arr):
print("array_rand3:")
size = len(arr)
arr2=arr.copy()
for x in range(0, size):
n = random.randint(0, size-1-x)
t = arr2[n+x]
arr2.pop(n+x)
arr2.insert(x, t)
print("{}".format(arr2))
print("打乱结果:{}".format(arr2))
return arr2
输出:1
2
3
4
5
6
7
8
9
10
11
12array_rand3:
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 5, 1, 2, 3, 4, 6, 7, 8, 9]
[10, 5, 7, 1, 2, 3, 4, 6, 8, 9]
[10, 5, 7, 1, 2, 3, 4, 6, 8, 9]
[10, 5, 7, 1, 9, 2, 3, 4, 6, 8]
[10, 5, 7, 1, 9, 4, 2, 3, 6, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
打乱结果:[10, 5, 7, 1, 9, 4, 6, 2, 3, 8]
方法4
对方法3进行优化
方法3使用了删除和插入操作比较耗费时间
并且考虑到从未乱序的数组中挑选元素时元素的顺序对挑选结果不造成影响。
任意元素选中概率为(1/(size-x))
因此可以把删除和插入元素修改为调换元素位置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#!/usr/bin/python3
# -*- coding: utf-8 -*-
import random
def array_rand4(arr):
print("array_rand4:")
size = len(arr)
arr2=arr.copy()
for x in range(0, size):
n = random.randint(0, size-1-x)
t = arr2[n+x]
arr2[n+x]=arr2[x]
arr2[x]=t
print("{}".format(arr2))
print("打乱结果:{}".format(arr2))
return arr2
输出:1
2
3
4
5
6
7
8
9
10
11
12array_rand4:
[4, 2, 3, 1, 5, 6, 7, 8, 9, 10]
[4, 3, 2, 1, 5, 6, 7, 8, 9, 10]
[4, 3, 1, 2, 5, 6, 7, 8, 9, 10]
[4, 3, 1, 9, 5, 6, 7, 8, 2, 10]
[4, 3, 1, 9, 7, 6, 5, 8, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 6, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 6, 2, 10]
[4, 3, 1, 9, 7, 8, 5, 10, 2, 6]
[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]
[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]
打乱结果:[4, 3, 1, 9, 7, 8, 5, 10, 6, 2]
方法5
对方法4进行优化1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def array_rand5(arr):
print("array_rand5:")
arr2=arr.copy()
l = len(arr2)
for i in range(0, l):
# 从剩下的数中随机选择一个数与arr[i]交换
# 每个数被选中的概率为1/(l-i)
n = random.randint(i, l-1)
# 交换arr[i]和arr[n]
t = arr2[n]
arr2[n]=arr2[i]
arr2[i]=t
print("{}".format(arr2))
print("打乱结果:{}".format(arr2))
return arr2
输出:1
2
3
4
5
6
7
8
9
10
11
12array_rand5:
[7, 2, 3, 4, 5, 6, 1, 8, 9, 10]
[7, 1, 3, 4, 5, 6, 2, 8, 9, 10]
[7, 1, 5, 4, 3, 6, 2, 8, 9, 10]
[7, 1, 5, 6, 3, 4, 2, 8, 9, 10]
[7, 1, 5, 6, 10, 4, 2, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 8, 9, 3]
[7, 1, 5, 6, 10, 2, 4, 3, 9, 8]
[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]
[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]
打乱结果:[7, 1, 5, 6, 10, 2, 4, 3, 8, 9]
完整代码
1 | #!/usr/bin/python3 |