c++ 排列组合_【超详细】一文学会排列组合

f1a5ff041b40343d774a5c77c1b42060.png

来源:码海

作者:子非鱼

上一篇「【超详细】一文学会递归解题」一文颇受大家好评,各大号纷纷转载,让笔者颇感欣慰,不过笔者注意到后台有读者有如下反馈

f279fbb7126b57c88e18fb057a4bc514.png

确实,相信很多人(包括我自己)都有类似的感慨,对某个知识点,看确实是看懂了,但如果真的再用同样的套路再去解一些带有同样解题思路,但稍加变形的题,往往会束手无策。对这种情况有啥好的解决办法吗?

除了勤加练习,还有一良策!

鲁迅先生说:如果学习算法,最好一段时间内只刷某种算法思想某种数据结构的题,啥意思呢?比如说你上次学了递归,那就持续找递归的题来刷,学了链表,这段时间就专门刷链表的题,千万不可今天刷递归,明天刷动态规划,后天又开始学习贪心算法。。。新手最怕的就是以为自己懂了,浅尝辄止,这是新手的大忌!一定要对同一类型的题穷追猛打,形成肌肉记忆,这样之后再碰到同一类型的题就会条件反射地一看:哦,这题用 xxx 思想应该可以靠谱。

2c1aa049f99909f4a67fe4dce078c914.png

言归正转,排列组合是面试中的热门考点 因为看似简单的排列组合可以有挺多的变形,根据变形,难度可以逐渐递增,而且排列组合本身有挺多的解法,能很好地区分一个侯选者的算法水平,排列组合如果用递归挺不容易理解的(反正笔者一开始看了好几遍代码愣是没看懂),之后我会教大家如何用一种非常简单地方式来理解排列组合的递归,这也是写本文的根本目的

接下来我们看看如何用 「递归四步曲」来解排列组合,本文会从以下几个方面来讲解排列组合

  1. 什么是排列
  2. 排列的常用解法
  3. 什么是组合
  4. 组合递归解法
  5. 面试中排列组合的一些变形

什么是排列

排列的定义:从n个不同元素中,任取 m (m≤n,m与n均为自然数,下同)个不同的元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,当 n = m 时,我们称这样的排列为全排列

看到这个公式,大家是不是回忆起了高中的排列公式啦e75a4f79c5407aa46b28cc6e70d31816.png

我们重新温习一下,以 1, 2, 3 这三个数字的全排列有多少种呢。

第一位我们可以选择 3 个数字,由于第二位不能与第一位相等,所以第二位只能选 2 个数字,第一,第二位既然选完了,那么第三位就只有 1 个数字可选了,所以总共有  3 x 2 x 1 = 6 种排列。699ca69f3830b2aa5b4101dbe0ae9160.png

既然知道了什么是全排列,那我们来看看怎么用程序来打印全排列的所有情况:求 数字 1 到 n (n < 10) 的全排列

排列的常用解法

这道题如果暂时没什么头绪,我们看看能否用最简单的方式来实现全排列,什么是最简单的方式,暴力穷举法!

暴力穷举法

大家仔细看上文中 1,2 ,3 的全排列,就是把所有情况全部列举出来了,所以我们用暴力穷举法怎么解呢,对每一位的每种情况都遍历出来组成所有的排列,再剔除重复的排列,就是我们要的全排列了

/**
* 求数字第 1 到 n 的全排列
*/
public void permutation(int n) {
for(int i = 1; i < n + 1; i ++) {
for(int j = 1; j < n + 1; j ++) {
for(int k = 1; k < n + 1; k ++) {
if (i != j && i != k && j != k) {
System.out.println(i + j + k);
}
}
}
}
}

时间复杂度是多少呢,做了三次循环,很显然是

很多人一看时间复杂度这么高,多数都会嗤之以鼻,但是要我说,得看场景,就这题来说用暴力穷举法完全没问题,n 最大才 9 啊,总共也才循环了 9^3

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值