美文网首页
面试题,使用递归解决排列组合问题

面试题,使用递归解决排列组合问题

作者: 茧城寒舍 | 来源:发表于2020-12-17 18:16 被阅读0次

1. 面试题目

公司6人,3人一组,分组如下:

t1 = {"A","B","C"}     # 会唱歌
t2 = {"a","b","c"}     # 会跳舞

两两结合,表演节目。

其中A和a不能同一组(两个人有杀父之仇!)

同一组不能成对,比如AB,BC,ab等等

全体成员必须全部参加。

要求:打印所有组合。

2. 解题思路

  1. 先找出2个组相互组合的所有情况

    >>> t1 = {"A","B","C"}
    >>> t2 = {"a","b","c"}
    >>> team_set = {el1+el2 for el1 in t1 for el2 in t2}
    >>> team_set
    {'Bc', 'Bb', 'Ba', 'Ca', 'Cb', 'Aa', 'Ab', 'Cc', 'Ac'}
    >>>
    
  2. 排除杀父仇人组合

    >>> team_set - {'Aa','aA'}
    {'Bc', 'Bb', 'Ba', 'Ca', 'Cb', 'Ab', 'Cc', 'Ac'}
    
  3. 递归调用选出合适的组合(核心部分)

3. 核心代码实现

我们先来验证最简单的组合,比如下面这种:

# 给定一个集合,包含若干元素
set1 = {"a","b","c"}
# 如果从中选择1个元素,有以下这么多组合
[{"a"},{"b"},{"c"}]

我们再看看从3元素中两两组合:

# 给定一个集合,包含若干元素
set1 = {"a","b","c"}
# 如果从中选择1个元素,有以下这么多组合
rst = [{"a","b"},{"b","c"},{"a","c"}]    # 肉眼可见,手动暴力组合得出的结果

# 1如果把原来的集合去除一个元素a,原来的集合变成
t1 = {"b","c"}
# 2如果从t1中选择1个元素有多少种组合呢
[{"b"},{"c"}]   # 这是在上文中提到过,貌似如果从集合中选择1个进行组合,是最简单的
# 3现在我们把原来的a加入到每个元素中去
[{"a","b"},{"a","c"}]
# 4我们把t1中再去除一个元素b,原来的集合变成:
t2 = {"c"}
# 5从t2中选择1个元素进行组合
[{"C"}]
# 6现在我们把原来的b加入到每个元素中去
[{"b","c"}]
# 7 把1-6步得到的结果组合起来就是
[{"a","b"},{"b","c"},{"a","c"}]   # 和我们肉眼所见,暴力组合一致
# 8 还有一种比较特殊的,比如从3个人中选择3个人
[{"a","b","c"}]

从上面的手动分析过程我们可以看到1-3步和4-6是重复的过程,那么可以封装成函数

def getRst(set,num):
    if len(set) == 0:   # 集合为空,直接返回空list
        return []
    if num == 1:        # 从集合中选1个进行组合
        return [{x} for x in set]
    elif len(set) == num:
        return [set]    # 要组合的人数如果和集合一直,直接返回,比如2个人的集合要选择2个人
    else:
        list_sum = []
        temp_set = set.copy()
        for i in range(len(set)):
            temp_el = temp_set.pop()
            for item in getRst(temp_set,num - 1):
                temp_item = item.copy()
                temp_item.add(temp_el)
                list_sum.append(temp_item)
        return list_sum

4. 验证

把刚才排入不能在一起的人的组合放进去验证:

rst = {'Bc', 'Bb', 'Ba', 'Ca', 'Cb', 'Ab', 'Cc', 'Ac'}

for item in getRst(rst,3):
  print(item)
  
  
  
# 结果如下:
{'Ac', 'Ab', 'Cb'}
{'Ac', 'Cb', 'Ca'}
{'Ac', 'Cb', 'Cc'}
{'Ac', 'Cb', 'Ba'}
{'Ac', 'Cb', 'Bc'}
{'Ac', 'Cb', 'Bb'}
{'Ab', 'Ca', 'Cb'}
{'Ab', 'Cc', 'Cb'}
{'Ab', 'Ba', 'Cb'}
....

从结果看,有1个人参与两次活动的情形,比如{'Ac', 'Cb', 'Bb'},如何去重呢,可以利用集合的属性

str_sum = ""
for item in {'Ac', 'Cb', 'Bb'}:
  str_num += item
print(len(set(str_num)))
# 结果是5,说明有人参加了两次,有人没有参加

那么我们对每个集合都做上面的操作得到想要的结果:

rst = {'Bc', 'Bb', 'Ba', 'Ca', 'Cb', 'Ab', 'Cc', 'Ac'}

for item in getRst(rst,3):
  str_sum = ""
  for str in item:
    str_sum += str
  if len(set(str_sum)) == 6:
    print(item)
    
    
# 结果如下:
{'Ac', 'Bb', 'Ca'}
{'Ac', 'Ba', 'Cb'}
{'Ab', 'Cc', 'Ba'}
{'Bc', 'Ab', 'Ca'}

相关文章

  • 面试题,使用递归解决排列组合问题

    1. 面试题目 公司6人,3人一组,分组如下: 两两结合,表演节目。 其中A和a不能同一组(两个人有杀父之仇!) ...

  • Python实现字符串排序(包含了排列组合问题)

    用递归的方式解决排列组合问题 def zuhe(ss,res,path): if ss == '': ...

  • Python yield

    参考:Python yield 使用浅析 - IBM 递归中使用yield 有时候yield就可以解决递归的问题,...

  • JAVA编程基础之递归结构

    递归结构 递归是一种常见的解决问题的方法,即把问题逐渐简单化。 递归的基本思想就是 自己调用自己 ”,一个使用递归...

  • 05 递归

    Haskell 中没有 for 和 while 循环,而使用递归解决循环问题。 所谓递归,就是将一个大问题分解为两...

  • 前端开发 -- 算法模式(递归和动态规划)

    递归 递归是一种解决问题的方法,它解决问题的各个小部分,直到解决最初的大问题,递归通常涉及到函数的自身调用。递归函...

  • Java--递归-1

      递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是“自己调用自己”,一个使用递归技术的方法...

  • 递归

    1.递归是什么? 定义:程序调用自身的编程技巧称为递归。递归使用的是选择结构,对于解决同样问题的孪生兄弟:迭代,它...

  • 学习递归

    1. 递归 1.1 理解递归 ​ 递归是一种解决问题的方法,它从解决问题的各个小部分中开始,直到解决最...

  • Js递归数组展平

    遇到多个嵌套的数组,将嵌套的数组中的元素全部展开到最外层的数组中,可以使用递归来解决这个问题。 什么是递归? 递归...

网友评论

      本文标题:面试题,使用递归解决排列组合问题

      本文链接:https://www.haomeiwen.com/subject/finzgktx.html