Python程序员面试算法宝典---解题总结: 第7章 排列组合与概率 7.1 如何求数字的组合

# -*- 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()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值