从m个数中选择n个数的组合
题目:从m个数选择n个数的所有组合
题解:思路参考01转换法
假设有一个长度为 m 的数组,我每次选取 n 个数组成一组,将所有的可能列举出来:
- 创建一个由 “0” 和 “1” 组成的数组,长度为 m,数组中 “1” 表示其下标所在的数被选中,为 “0” 则没选中;
- 初始化该数组,将数组前 n 个元素置 “1” ,表示第一个组合为前 n 个数;
- 然后从左到右扫描数组元素值的 “10” 组合,找到第一个 “10” 组合后将其变为 “01” 组合;
- 同时将其左边的所有 “1” 全部移动到数组的最左端;
- 当 n 个 “1” 全部移动到最右端时,就得到了最后一个组合,组合结束。
例子:“从6个数中选出3个数” 步骤如下:
- 构建初始化选中下标 111000
- 扫描第一个“10”转化为“01”,得到结果110100
- 移动“01”左边所有“1”到最左边,得到结果110100
- 重复2~3步骤,直到没有“10” 以上步骤即可得到所有结果
具体代码实现如下:
const test = function(m, n) {
if (n < 1 || m < n) return []
const result = []
// 初始化选中下标
let str = '1'.repeat(n) + '0'.repeat(m - n)
result.push(str.split(''))
while(str.indexOf('10') >= 0) {
// 找到第一个10 替换成01
const idx = str.indexOf('10')
str = str.slice(0, idx) + '01' + str.slice(idx + 2)
// 移动idx左边的到最左边
let prefix = str.slice(0, idx)
const oneArr = str.slice(0, idx).match(/[1]/g)
if (oneArr && oneArr.length) {
prefix = '1'.repeat(oneArr.length) + '0'.repeat(prefix.length - oneArr.length)
}
str = prefix + str.slice(idx)
result.push(str.split(''))
}
return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
上次更新: 2025/09/05, 8:09:00