在第一份工作结束的时候,还是个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. asp.net中显示DataGrid控件列序号的几种方法
  2. HTML从入门到进阶修炼
  3. linux获取目标主机shell,expect案例-批量获取主机并分发密钥
  4. 精简版开发工具使用手记(图解)
  5. 在JavaScript文件中读取properties文件的方法
  6. Caffe学习笔记2
  7. 春节特惠活动┃强烈推荐!孩子的科普从这套全球畅销250万册的最酷科学书起步...
  8. C语言 素数三种思路求解,C语言求素数
  9. 基于Windows XP SP3系统下MS08067漏洞攻击
  10. LCS算法和背包算法
  11. 量子计算机能做到0延迟吗,延迟选择量子擦除实验
  12. 关于PHP=5.5时密码哈希校验的使用案例
  13. 单片机控制电路的多图纸原理图和层次式设计
  14. CAD编辑工具中如何查找图纸中的坐标点的位置
  15. 真正的IT技术男是什么样的?
  16. AE鱼眼镜头畸变扭曲修复插件:RevisionFX RELens for Mac
  17. 世上无难事,只怕有心人!
  18. 植物大战僵尸一:多线程修改UI界面,游戏必备API
  19. 暴力破解zip压缩包
  20. 计算机桌面怎么突然变大了,电脑桌面比例突然变大?一招还原比例!

热门文章

  1. 【元胞自动机】元胞自动机双边教室疏散【含Matlab源码 1208期】
  2. 在不同操作系统上安装Python的详细教程
  3. 【Mo 人工智能技术博客】基于耦合网络的推荐系统
  4. MySQL的my-innodb-heavy-4G.ini配置文件的翻译
  5. 锚定情境法:有效控制变量自评偏差
  6. Spring-全面详解(基础知识)
  7. IE显示对象不支持此属性或方法 的解决方法
  8. 计算机脚本语言是什么?
  9. 分子力场简介 来自wiki百科
  10. TI公司之DSP结构与芯片