在最简单的情况下,数字集中只有一个数字,比如1,那么对于1来说全排列非常简单,就是1,这样我们解决了这个问题的第一步。
接下来我们来到了第二步,此时多了一个数字2,在第一步中我们已经知道了1的全排列是什么,那么我们该如何利用这一信息呢?
对于1来说形成的全排列就是:
1
此时再给你一个数字2,那么就会有两种可能:
把2放到1的开头,从而形成21
把2放到1的结尾,从而形成12
这个过程如图所示:
就这样我们处理完了第二个数字。
怎么样,现在你看明白这个策略了吧,也就是我们利用上一步的计算结果把当前的数字放到上一个全排列的数字串的各个位置上就可以了。
接下来我们来到了数字3,在上一步中我们得到了{12,21},在这一部中我们继续利用上一步的结果,我们首先来看上一步中的12,这时我们可以:
把3放到12的开头,从而形成312;
把3放到12的中间,从而形成132;
把3放到12的结尾,从而形成123;
这个过程如图所示:
利用完了上一步中的12,接下来就是21,基于同样的道理,我们可以得到:321、231以及213,如图所示:
至此,我们计算出了{1,2,3}这个数据集的全排列,这些全排列就位于数的最后一层,如图所示:
现在你应该明白这个策略了吧,那就是不断利用上一步的计算结果形成加入当前数字的全排列,直到所有数字用完为止。
实际上上面这句话就是解决该问题的算法啦。
接下来我们就把上面这句中文翻译成C++代码。
代码实现
这里唯一需要说明的是,上面生成排列的方法涉及到字符串的拼接,因此使用list这种数据结构加快速度。
总结
在这个问题中我们依然从最简单的情况着手,逐步增加问题难度,最终我们发现了解决问题的策略,最关键的值,这种清晰描述的策略不但程序员能明白,CPU也能理解,这样我们才有可能将我们人类理解的事情告诉计算机,这里再一次体现了 如果作为程序员你不能清晰的描述你对一个问题的理解,那么想写出能正确运行的程序是不可能的。
当然,如果真正的人工智能能够实现的话当我没说 :)
扫码,京东优惠购书
大礼包:凡是在 京东购书并评价的(必须有评价),请将截图发到邮箱:itbook8@163.com,免费获取额外赠送的ACM题库资源。