# -*- coding: utf-8 -*-
'''
Python程序员面试算法宝典---解题总结: 第7章 排列组合与概率 7.1 如何求数字的组合
题目:
用1、2、2、3、4、5这6个数字,写一个main函数,打印出所有不同的排列。
例如: 512234、412345等,要求:
4不能在第三位,3与5不能相连。
分析:
之前有遇到过通过不断交换第一位与后面一位的数字来计算排列的字符串组合
算法。在那个算法中还可以去除重复情况,
添加各种限制条件。
这里的限制条件应该也是可以设置的。
字符串排列算法的主要思想:
举例:
abc是初始字符串,
固定第一个字符a,对后面字符bc进行全排列
然后交换第一个字符和其后面的字符,即交换ab,
然后固定第一个字符b,对后面的两个字符ac进行群偏离额
再次交换a与b
交换ac,固定第一个字符c,对ab进行全排列
关键:
1 4不能在第三位可以在最后输出所有结果的时候,过滤这种情况
2 3与5不能在一起,可以在排列算法计算的时候过滤
3 排列算法
设置起始位置start,设置交换下标i,i取值为start到len-1
while i < len:
过滤条件
...
交换第start位与第i位
递归计算start+1位
交换第start位与第i位
设定后续交换位变为i+1
参考:
Python程序员面试算法宝典
https://blog.csdn.net/qingyuanluofeng/article/details/94286313
'''
def swap(charList, i, j):
if not charList or i < 0 or j < 0 \
or i >= len(charList) or j >= len(charList):
return
temp = charList[i]
charList[i] = charList[j]
charList[j] = temp
def isDuplicated(charList, start, i):
if not charList:
return False
size = len(charList)
if start >= size or i >= size or start < 0 or i < 0:
return True
for index in range(start, i):
if charList[index] == charList[i]:
return True
return False
'''
4不能在第三位,3与5不能相连。
'''
def isOk(charList, start, i):
if not charList:
return False
size = len(charList)
if start >= size or i >= size or start < 0 or i < 0:
return False
# 交换之前也不能存在3与5相连
if not is3And5Ok(charList):
return False
# 交换之后也不能存在3与5相连
swap(charList, start, i)
if not is3And5Ok(charList):
# 还原
swap(charList, start, i)
return False
else:
swap(charList, start, i)
return True
def is4Ok(charList, index=2):
char = charList[index]
if char != '4':
return True
else:
return False
def is3And5Ok(charList):
if not charList:
return True
size = len(charList)
filterSet = set(['35', '53'])
for i in range(1, size):
temp = charList[i-1] + charList[i]
if temp in filterSet:
return False
return True
def permutation(charList, start):
if not charList or start < 0:
return
size = len(charList)
if start == size - 1:
# 4不能在第三位
if is4Ok(charList):
result = "".join(charList)
print result
i = start
while i < size:
# 过滤重复的
if isDuplicated(charList, start, i):
i += 1
continue
# 3与5不能相连。
if not isOk(charList, start, i):
i += 1
continue
# 交换字符
swap(charList, start, i)
# 固定一个字符,求剩余字符的全排列
permutation(charList, start + 1)
# 恢复字符串顺序
swap(charList, start, i)
# 重新设定后续的交换字符
i += 1
def process():
# string = "abc"
# charList = list(string)
# permutation(charList, 0)
# print "############"
# string = "abbc"
# charList = list(string)
# permutation(charList, 0)
print "####################"
string = "122345"
charList = list(string)
permutation(charList, 0)
if __name__ == "__main__":
process()