题目:有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?
来看第一种解法
1 num = [1, 2, 3, 4] 2 """ 3 根据题中'互不相同'要求,创建一个集合(去重),存放三位数 4 注意{}仅用于创建空字典!set()函数用来创建集合 5 """ 6 s = set() 7 # 遍历整个列表三次,组成三位数 8 for i in num: 9 for j in num: 10 # 去掉与i重复的数字 11 if j !=i: 12 for k in num: 13 # 去掉与i,j重复的数字 14 if k != j and k != i: 15 n = 100*i + 10*j + k 16 # 注意集合添加元素的方法为add和update 17 s.add(n) 18 print("无重复的三位数个数:", len(s)) 19 print("分别是:", s)
这种解法时间复杂度为O(n2), 其中的列表可以换成range生成器
1 s = set() 2 # 遍历整个列表三次,组成三位数 3 for i in range(1, 5): 4 for j in range(1, 5): 5 # 去掉与i重复的数字 6 if j !=i: 7 for k in range(1, 5): 8 # 去掉与i,j重复的数字 9 if k != j and k != i: 10 n = 100*i + 10*j + k 11 # 注意集合添加元素的方法为add和update 12 s.add(n) 13 print("无重复的三位数个数:", len(s)) 14 print("分别是:", s)
以上两种解法都可以改成列表推导式的形式,如下,这种形式看上去简洁,但如果出错了排查起来比较困难,一般不推荐使用
lst = [100*i + 10*j + k for i in num for j in num for k in num if (i != j and j != k and k != i)]
第三种方法比较野路子,先确定最终数的范围,然后一个一个判断,当然这种效率是极低的
1 s = set() 2 # 缩小范围,三位数肯定在123和433之间 3 for i in range(123, 433): 4 # 个位数字 5 a = i%10 6 # 十位数字 7 b = (i%100)//10 8 # 各位数字 9 c = (i%1000)//100 10 if a != b and b != c and a != c and 0 < a < 5 and 0 < b < 5 and 0 < c < 5: 11 s.add(i) 12 print("无重复的三位数个数:", len(s)) 13 print("分别是:", s)
第四种方法是运用python的内置函数permutations,其语法格式为:
permutations(iterable[, r]),返回一个长度为r的元组
代码如下:
from itertools import permutations # permutations返回3位长度的元组,permutations意为交换 s = set() for i in permutations([1, 2, 3, 4], 3): k = '' for j in range(0, len(i)): k = k + str(i[j]) s.add(int(k)) print("无重复的三位数个数:", len(s)) print("分别是:", s)
总结
第一、二种方法比较接近,都是for循环嵌套加判断求解,第三种方法比较另类,先判断一个大致范围再遍历,第四种方法运用python内置的permutations函数直接生成包含3个数字的元组。综合来看,第四种方法更简洁