团队内Feedback收集活动,如何用回溯算法排组?

152 阅读4分钟

背景:

Feedback是Thoughworks的敏捷文化之一,​也是我们团队的文化建设活动。在团对内定期的One-On-​One收集Feedback好处非常多。

对团队而言,可以促进团队成员间的交流,带动日常持续反馈,​营造良好的团队氛围,从而提升团队凝聚力。对个人而言,​持续的接收反馈可以提升自我意识和个人认知,​激励个人发展和持续进步,持续的给出反馈也可以帮助他人成长。

为了在团队内更加高效的Feedback,​每次活动前都需要提前安排每轮的名单和顺序。在保证每个团队成员​之间都轮流到的情况下,为节省中途等待时间,需安排的轮数最少。​即人数为奇数时,轮数=人数,人数为偶数时,轮数=人数 - 1。

不知不觉中,我们团队越来越壮大,成员已经到达13人。​跟以前一样开始进行手工排组,排着排着发现,​总有重复或轮空的情况。​大家都满怀热情的加入了最优排序的讨论中,排了好几轮,​最终排出来的最优轮数是14,没有达到最优轮数,​并且还花费了近两个小时,团队人数越多排组越费时。

为解决人工排组的时间消耗问题,​也为了后续更高效的进行Feedback收集活动,​开启了自动化排组。

以【A,B,C,D,E,F】6个成员为例的排组思路

  1. 生成不重复的两两成员组合关系。

    [ 'A', 'B' ], [ 'A', 'C' ], [ 'A', 'D' ], [ 'A', 'E' ], [ 'A', 'F' ],
    [ 'B', 'C' ], [ 'B', 'D' ], [ 'B', 'E' ], [ 'B', 'F' ],
    [ 'C', 'D' ], [ 'C', 'E' ], [ 'C', 'F' ],
    [ 'D', 'E' ], [ 'D', 'F' ],
    [ 'E', 'F' ]
    
  2. 确定成功条件,也就是选出来的组合中,​每个成员都包含在内且没有重复出现。

    例如 [ 'A', 'B' ], [ 'C', 'D' ], [ 'E', 'F' ]。

  3. 确定重新开始循环的条件和结束条件,​得到一个满足成功条件的解之后,剔除已分配的组合,​避免重复选择。并在剩余的组合里面,​从头开始循环匹配下一个满足成功条件的解,​直到所有的组合分配完毕。

  1. 确定剪枝条件,当循环到重复的成员时,就跳出当前循环,​不继续匹配下一个组。

    例如第一组为[ 'A', 'B' ],循环的下一个是[ 'A', 'C' ],出现重复成员的'A',表示第二组没有寻找成功,​不开始找第三组,而是继续找第二组,直到找到了没有重复成员的[ 'C', 'D' ],再从[ 'C', 'D' ]的下一个开始往后找第三组。

  1. 确定回溯点撤销操作,当前选择不满足成功条件时,​撤销上一步操作之后再继续循环。

    例如在寻找第二个满足成功条件的解时,匹配到的第一个组是[ 'A', 'C' ], 找到的满足不重复条件的第二个组是[ 'B', 'D' ],再继续匹配第三组时,​直到循环结束都没有找到满足成功条件的第三组,因为能匹配的[ 'E', 'F' ]在上一次已经被选择。这时就需要撤销上一步选择,​把第二组选择[ 'B', 'D' ]撤回,从[ 'B', 'D' ]的下一个[ 'B', 'E' ]重新开始循环,[ 'B', 'E' ]是符合的第二组,则继续找第三组[ 'D', 'F' ]。

  1. 最终结果。

    组1:[ 'A', 'B' ], [ 'C', 'D' ], [ 'E', 'F' ]

    组2:[ 'A', 'C' ], [ 'B', 'E' ], [ 'D', 'F' ]

    组3:[ 'A', 'D' ], [ 'B', 'F' ], [ 'C', 'E' ]

    组4:[ 'A', 'E' ], [ 'B', 'D' ], [ 'C', 'F' ]

    组5:[ 'A', 'F' ], [ 'B', 'C' ], [ 'D', 'E' ]

  1. 人数为奇数时,每次会有一位成员轮空,排组时可以添加占位成员。 例如:7个成员时,就以8个成员来排组【A,B,C,D,E,​F,G, 轮空】。

源码地址

回溯算法回顾:

回溯算法也叫试探法,是一种选优搜索法,按选优条件向前搜索,​以达到目标。主要是在搜索尝试过程中寻找问题的解,​当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

简单来说:

回溯法可以理解为通过选择不同的岔路口,来寻找目的地,​一个岔路口一个岔路口地去尝试找到目的地,如果发现走错了路,​继续返回到上一个岔路口,选择其它路,直到找到目的地。

用回溯算法解决问题的基本步骤:

  1. 针对所给问题,定义问题的解空间,它至少包含问题的一个解;

  2. 确定易于搜索的解空间结构,使得能用回溯法方便地搜索整个解空间 ;

  3. 以深度优先的方式搜索解空间,​并且在搜索过程中用剪枝函数避免无效搜索。

核心要素:

  1. 「递归出口」:包括成功条件和剪枝条件。​剪枝条件是回溯优化的方法,通过这个函数,​可以剪去一些不可能到达成功条件的路径,​就减少了无效路径的生成;
  2. 「选择列表」:存储满足选择条件的操作;
  3. 「路径」:记录做出的选择,递归调用,进入下一层;​不选择则撤回,回到上一步。