在第一份工作结束的时候,还是个java小白,找工作的时候去面试,碰到一个算法题:

从十个数字中选取八个数字排列,重复算一个,一共有多少种可能?

当时想了半天也没想出来,虽然是数学上的排列组合算法,但是还是想自己思考下解决方案。

今天发一下自己的解决思路,思路很简单,适合初级程序员:

1、假定max个数,抽取min个数字

2、初始化一个组合为数字 0-min

3、固定min-1个数字,找出其中一个数字的可替换可能,从高min到低0依次替换第cou位数字

4、替换前设定第cou位之后到min位的数字全为-1

5、替换第cou位,若发现所有组合数字全部替换完毕,则是一种组合,否则,替换第cou+1位(迭代)

有几个替换原则了解一下:

1、替换cou位数字的值一定要大于cou位数字,例如:0-2-?,?一定要大于2,可以保证所有的组合都是从小到大排列,既不会重复

2、替换cou位数字完毕之后,一定要依次替换cou位之后为-1的,直到替换到最后一位,例如:1-?-? 第一次替换位1-2-?,       要接着替换第三位为1-2-3,1-2-4

接下来,用代码来了解一下:

package com.lytx.ims.aa;import java.util.ArrayList;
import java.util.List;/*** max十个数选取min个有多少种组合,不要求顺序* @author Administrator**/
public class TenNumberTest {/*** 第一次初选组合*/private int[] orignal;/*** 选取数字池*/private int[] pools;private int max;private int min;/*** 要替换的组合数字下标*/private int cou; /*** 存放所有的组合*/private List<String> list = new ArrayList<String>();/*** 构造函数* @param max* @param min*/public TenNumberTest(int max, int min) {this.setMax(max);this.setMin(min);this.setCou(min - 1);//数组下标从0开始,替换从min-1的下标开始int[] pools = new int[max];for (int i = 0; i < max; i ++) {pools[i] = i;}//max位数字组成的数字池this.setPools(pools);int[] orginal = new int[min];for (int i = 0; i < min; i ++) {orginal[i] = i;}//第一次选取的初始组合,0-minthis.setOrignal(orginal);}public void change() {//初始组合加入到list中list.add(toStr(this.orignal));/*** 该循环替换cou位到第0位下标的数字*/while (true) {this.change(this.orignal.clone(), this.cou);this.cou -- ;if (this.cou < 0) {//替换完第0位下标-跳出循环break;}}}/*** 获取组合的可行性数量* @return*/public int getCount() {return list.size();}/*** @param currentSelect 已选* @param start    替换下标*/public void change(int[] currentSelect, int start) {for (int i = start+1; i < currentSelect.length; i ++ ) {currentSelect[i] = -1;}next(currentSelect, start);}/*** 核心方法:* 替换下一个数字*/public void next(int[] currentSelect, int start) {/*** num值含义:* 替换的数字起始值,例如:0-2-?  , ?起始值是3  ;1-?-? , 需要先替换第一个?起始值是2 ;*                    注意:?-?-? 需要替换第一个?,起始值是1(因为0是初始组合,已经遍历完所有0开头的组合)* 这里需要判断替换的值是第几位,第0位下标则从1开始,往后的start位,需要大于start-1位的数字跟下标。*/int num = start == 0 ? 1 : currentSelect[start -1] + 1 < this.cou + 1 ? this.cou + 1 : currentSelect[start -1] + 1;for (int i = num; i < this.max; i++) {//遍历可以替换的值currentSelect[start] = this.pools[i];if (start == currentSelect.length - 1) {//替换的下标是最后一位下标,所有值已替换完毕,新增到组合list.add(toStr(currentSelect));} else {//还有下一个?值未替换,替换下一个值start + 1next(currentSelect.clone(), start + 1);}}}/*** 将当前已选值组成字符串0-1-2...* @return*/private String toStr(int[] select) {StringBuffer sb = new StringBuffer();for (int i = 0; i < select.length; i++) {if (i > 0) {sb.append("-");}sb.append(select[i]);}return sb.toString();}public static void main(String[] args) {/*** 测试一下,6个选2个*/TenNumberTest test = new TenNumberTest(6, 2);test.change();System.out.println(test.getList());System.out.println(test.getCount());}public List<String> getList() {return list;}public void setList(List<String> list) {this.list = list;}public void addList(String str) {this.getList().add(str);}public int getCou() {return cou;}public void setCou(int cou) {this.cou = cou;}public int[] getOrignal() {return orignal;}public void setOrignal(int[] orignal) {this.orignal = orignal;}public int[] getPools() {return pools;}public void setPools(int[] pools) {this.pools = pools;}public int getMax() {return max;}public void setMax(int max) {this.max = max;}public int getMin() {return min;}public void setMin(int min) {this.min = min;}
}

控制台输出结果:

[0-1, 0-2, 0-3, 0-4, 0-5, 1-2, 1-3, 1-4, 1-5, 2-3, 2-4, 2-5, 3-4, 3-5, 4-5]

15

结果为15种组合。

核心思想跟方法理解之后,就不难了解这个算法,这是一种比较简单的算法,以前还见过用二进制去算,如果大家有的好的算法,可以一起讨论下!

如何实现从M个数字选取N个数字排列算法相关推荐

  1. 通信应用中数字上变频DUC与数字下变频DDC详细原理(带图)

    目录 关于上下变频的仿真: 数字插值滤波与数字正交上变频的仿真与实验----基于高速DAC芯片 数字正交下变频与数字滤波抽取的仿真与实验----基于高速ADC芯片 1.DUC与DDC的应用场景来源[2 ...

  2. python开源数字识别_[转]:手写数字识别系统之数字提取

    引言 所谓数字分割就是指将经过二值化后的图像中的单个数字区域进行提取的过程.数字分割在数字识别中是一个必不可少的关键步骤,只有能够将数字进行准确的提取,才能将其一一识别. 数字分割的方法 数字分割的方 ...

  3. 手写数字识别系统之数字提取

    引言 所谓数字分割就是指将经过二值化后的图像中的单个数字区域进行提取的过程.数字分割在数字识别中是一个必不可少的关键步骤,只有能够将数字进行准确的提取,才能将其一一识别. 数字分割的方法 数字分割的方 ...

  4. 【数字孪生】关于数字孪生的冷思考及其背后的建模和仿真技术

    来源:系统仿真学报 张霖                          北京航空航天大学教授.曾任国际建模仿真学会(SCS)主席,北 航自动化   学院副院长等,现为ASIASIM主席,中国仿真学 ...

  5. js 判断是不是数字||判断字符串是不是数字(正则表达式)

    js使用正则表达式判断对象是不是数字,或者字符串是不是数字,或者是不是数字类型 1 //判断是不是一个数字 或者 一个字符串里全是数字 2 isNumber (value) { 3 if (value ...

  6. js 数字递增递减_数字推理满分技巧 !不是干货,请批我!

    公众号:兼得公考 数字推理不是广东的特色考点,但广东的数字推理是比较有"特色"的,他的特色就是简单,特别是2019年的数字推理.但我们不能因为某一两年考得简单而简单地学,为了让大家 ...

  7. C将十六进制数字字符串转成数字

    1.将十六进制数字字符串转成数字 long   lTemp   =   strtol("0xa10b", NULL, 16); 这样的话,就将0xa10b这个十六制形式的字符串转为 ...

  8. python 如何将字符串数字列表转换成数字列表,如何将数字列表转换成字符串数字列表?map(eval,list(str))

    字符串数字列表转换成数字列表 # -*- encoding: utf-8 -*- """ @File : test.py @Time : 2019/10/28 23:37 ...

  9. 怎样能用计算机打出表白数字,怎么用数字表白?盘点数字表白暗语

    怎么用数字表白?盘点数字表白暗语 时间:2020-05-03 19:43:06来源:考试帮手网作者:敏敏 表白的方法有很多,大家用过最多的就是文字表白,大家有没有听说过用数字表白呢?数字表白如今已经成 ...

最新文章

  1. 互补输出级采用共集形式是为了使_互补输出级采用共集形式是为了使
  2. Error in apply(df$var1, 2, mean) : dim(X) must have a positive length
  3. 其他资源记录类型及应用示例
  4. mysql安装start service错误_为什么安装mysql会出现start service错误
  5. PE格式详细讲解4 - 系统篇04|解密系列
  6. scrapy mysql 报错_scrapy爬数据存mysql报错
  7. GitLab 安装笔记
  8. OpenStack运维面试(1)
  9. 技术选型:Sentinel vs Hystrix
  10. [转载] 利用python对csv文件进行简单的数据分析
  11. python类中导入库_python导入库的具体方法
  12. mysql linux 表名区分大小写吗_MySQL在linux下的表名如何不区分大小写
  13. SCM供应链管理系统解决方案:助力企业采购流程高效运行,全面降低供应链风险
  14. 【Task02】Pandas之基础
  15. 使用命令设置Windows音量和音频输出设备
  16. python余弦定理_余弦定理与文本相似度
  17. 新页微SOC无线充芯片NY7506A
  18. 【线上直播】人机多轮对话的方法综述
  19. 厦门吾智美:ESS.OIL.CO潜力无限
  20. 直播课报名 | 2022 看云计算如何赋能跨境电商企业再增长

热门文章

  1. UDF、UDTF、UDAF自定义函数
  2. 【数据库】ER模型的简单例子
  3. 局域网内,如何使用命令行关闭别人的电脑
  4. Android 多窗口适配
  5. 致创业新人,我网络创业的一些心得。
  6. 熬夜爆肝!C++基础入门大合集【万字干货预警 建议收藏】
  7. c语言编程雅可比迭代法方程,雅可比迭代法解方程组的C\C++程序
  8. 变量的作用域和生存期:_生存分析简介:
  9. 一个想法照进现实-《IT连》创业项目:关于团队组建
  10. 你为什么会选择做程序员?