求1~19整数中,求出和为20的组合
2015-10-27 07:15
405 查看
之前去公司面试,其中有一道问题是如何在1~19中,和为20的组合有多少个?(注意:数字不重复跟不颠倒。例如:1+1+1.....=20,19+1和1+19是一样的)。
我的思路比较简单,纯粹利用三重循环来求出组合。显然我就是算法薄弱的人(效率太低了),现在想想算法真的很重要。另外,下面贴的代码是从网上摘下来的(利用递归思想),我看了几天才看懂,没办法有点笨。不嫌弃的话继续看我分析,如有不当之处,请指出。废话少说,先贴出代码再分析。
public class Test
{
static int array[]; // 定义一个数组,用来保存带排序的数字(1~19)
static int count; //这是我测试加的,来测试 函数执行 的次数(大家可以不管)
static int num; //这是我测试加的,来测试 等于20的组合 有多少(大家可以不管)
static //静态初始化块,即new一个Test类,就会自动执行static里面的内容(只执行一次)
{
array = new int[19];
for (int i = 1; i <= 19; i++)
{
array[i - 1] = i;
}
}
//核心方法
//tmp[]是临时数组,arrayIndex,tmpIndex分别是2个数组的索引
static void combination(int array[], int tmp[], int arrayIndex, int tmpIndex)
{
count++;//统计函数调用的次数
if (tmpIndex == array.length)
{
return;
}
for (int i = arrayIndex; i < array.length; i++)//arrayIndex,tempIndex参数的初始值为0
{
tmp[tmpIndex] = array[i];
int result = 0;
for (int z = 0; z <= tmpIndex; z++)
{
result += tmp[z];
}
if (result == 20)
{ num++;
for (int j = 0; j <= tmpIndex; j++)
{
System.out.print(tmp[j] + "+");
}
System.out.println("=20");
return; //优化效果部分(等于20后不用试后面的数字)
}
else if (result > 20)
{
return;
}
combination(array, tmp, i + 1, tmpIndex + 1);//递归调用
}
}
public static void main(String[] args)
{
combination(array, new int[19], 0, 0);
System.out.println("count------"+count);
System.out.println("num------"+num);
}
}
执行结果
1+2+3+4+10+=20
1+2+3+5+9+=20
1+2+3+6+8+=20
1+2+3+14+=20
1+2+4+5+8+=20
1+2+4+6+7+=20
1+2+4+13+=20
1+2+5+12+=20
1+2+6+11+=20
1+2+7+10+=20
1+2+8+9+=20
1+2+17+=20
1+3+4+5+7+=20
1+3+4+12+=20
1+3+5+11+=20
1+3+6+10+=20
1+3+7+9+=20
1+3+16+=20
1+4+5+10+=20
1+4+6+9+=20
1+4+7+8+=20
1+4+15+=20
1+5+6+8+=20
1+5+14+=20
1+6+13+=20
1+7+12+=20
1+8+11+=20
1+9+10+=20
1+19+=20
2+3+4+5+6+=20
2+3+4+11+=20
2+3+5+10+=20
2+3+6+9+=20
2+3+7+8+=20
2+3+15+=20
2+4+5+9+=20
2+4+6+8+=20
2+4+14+=20
2+5+6+7+=20
2+5+13+=20
2+6+12+=20
2+7+11+=20
2+8+10+=20
2+18+=20
3+4+5+8+=20
3+4+6+7+=20
3+4+13+=20
3+5+12+=20
3+6+11+=20
3+7+10+=20
3+8+9+=20
3+17+=20
4+5+11+=20
4+6+10+=20
4+7+9+=20
4+16+=20
5+6+9+=20
5+7+8+=20
5+15+=20
6+14+=20
7+13+=20
8+12+=20
9+11+=20
可能大家还是不太明白是怎么一回事吧?递归理解好了问题就解决了!
首先,大家先不用急,给你们看个下例子 再去理解上面的题目就好多了。
现在有个这样的情况:
public class Test1 {
static int count = 0;
static void show(){
for(int i=1;i<=10;i++){
count++;
if(count>1){System.out.println("count的值为:"+count);return;}
show();
System.out.println("LOL I love!");
}
}
public static void main(String[] args) {
show();
}
}
问控制台会输出什么?
输出的结果为:
count的值为:2
LOL I love!
count的值为:3
为什么会这样呢?大家跟我来分析流程。1.程序首先进入main方法调用show().
2.count的初始值为0,第一次show()方法中count变为了1->程序执行if下面的show()方法(此时暂时不会执行show下面的输出语句)。程序重新执行show方法,因为count是全局变量,因此 此时的count变为2(大家请注意 for循环里面的 i 的值并未 为2,还是从1开始。因为递归的各个局部变量是保存在堆栈里面的)。3.此时的count>1输出 count的值为:2,return后此次递归结束,返回结果给上一层。此时继续执行步骤2中中断的路程(也就是show下面的输出语句).此时输出 LOL
I love!(大家注意count是全局变量,现在仍未2 )因为此时的i=1,因此会在执行一次循环,输出结果为 count的值为:3
比较简洁的描述为:
1.count = 0 ,show()开始执行,count = 1。
2.递归调用show() ,count = 2,输出 count的值为:2,此时 i=1。
3.第二个show()执行遇到结束条件 return;返回上一层的状态
4.执行第一次show下面的输出方法 输出 LOL I love!
5.第一层状态的 i 也为1(<10),count = 3 ,输出 count的值为:3,递归结束(此时不会执行下面的show方法了,因为递归是先从上往下调用,然后从下往上返回结果,重新返回到第一层状态时候递归就结束了,这点大家可能不是很好理解。)
因此,了解了递归,就可以轻松了解1~19中组成20数字的递归解法了。程序运行是这样的顺序
1.arrayIndex初始值为0 array[arrayIndex]=1<20
2..arrayIndex++
array[0~arrayIndex]=1+23<20 .......arrayIndex
= 5 array[0~5]=1+2+3+4+5+6=22>20 此时一共调用了6层方法,因为22>20,所以第六层递归满足结束的条件。于是第五个加数就不存在了,第四个加数加1(没掉一层combination方法,加数就增加一个).以此类推
3.展示第一个结果
①.1+2+3+4+5+6=22>20--->②.1+2+3+4+6=21>20----->③.1+2+3+4+7<20......1+2+3+4+10=20.第四层递归结束
我的思路比较简单,纯粹利用三重循环来求出组合。显然我就是算法薄弱的人(效率太低了),现在想想算法真的很重要。另外,下面贴的代码是从网上摘下来的(利用递归思想),我看了几天才看懂,没办法有点笨。不嫌弃的话继续看我分析,如有不当之处,请指出。废话少说,先贴出代码再分析。
public class Test
{
static int array[]; // 定义一个数组,用来保存带排序的数字(1~19)
static int count; //这是我测试加的,来测试 函数执行 的次数(大家可以不管)
static int num; //这是我测试加的,来测试 等于20的组合 有多少(大家可以不管)
static //静态初始化块,即new一个Test类,就会自动执行static里面的内容(只执行一次)
{
array = new int[19];
for (int i = 1; i <= 19; i++)
{
array[i - 1] = i;
}
}
//核心方法
//tmp[]是临时数组,arrayIndex,tmpIndex分别是2个数组的索引
static void combination(int array[], int tmp[], int arrayIndex, int tmpIndex)
{
count++;//统计函数调用的次数
if (tmpIndex == array.length)
{
return;
}
for (int i = arrayIndex; i < array.length; i++)//arrayIndex,tempIndex参数的初始值为0
{
tmp[tmpIndex] = array[i];
int result = 0;
for (int z = 0; z <= tmpIndex; z++)
{
result += tmp[z];
}
if (result == 20)
{ num++;
for (int j = 0; j <= tmpIndex; j++)
{
System.out.print(tmp[j] + "+");
}
System.out.println("=20");
return; //优化效果部分(等于20后不用试后面的数字)
}
else if (result > 20)
{
return;
}
combination(array, tmp, i + 1, tmpIndex + 1);//递归调用
}
}
public static void main(String[] args)
{
combination(array, new int[19], 0, 0);
System.out.println("count------"+count);
System.out.println("num------"+num);
}
}
执行结果
1+2+3+4+10+=20
1+2+3+5+9+=20
1+2+3+6+8+=20
1+2+3+14+=20
1+2+4+5+8+=20
1+2+4+6+7+=20
1+2+4+13+=20
1+2+5+12+=20
1+2+6+11+=20
1+2+7+10+=20
1+2+8+9+=20
1+2+17+=20
1+3+4+5+7+=20
1+3+4+12+=20
1+3+5+11+=20
1+3+6+10+=20
1+3+7+9+=20
1+3+16+=20
1+4+5+10+=20
1+4+6+9+=20
1+4+7+8+=20
1+4+15+=20
1+5+6+8+=20
1+5+14+=20
1+6+13+=20
1+7+12+=20
1+8+11+=20
1+9+10+=20
1+19+=20
2+3+4+5+6+=20
2+3+4+11+=20
2+3+5+10+=20
2+3+6+9+=20
2+3+7+8+=20
2+3+15+=20
2+4+5+9+=20
2+4+6+8+=20
2+4+14+=20
2+5+6+7+=20
2+5+13+=20
2+6+12+=20
2+7+11+=20
2+8+10+=20
2+18+=20
3+4+5+8+=20
3+4+6+7+=20
3+4+13+=20
3+5+12+=20
3+6+11+=20
3+7+10+=20
3+8+9+=20
3+17+=20
4+5+11+=20
4+6+10+=20
4+7+9+=20
4+16+=20
5+6+9+=20
5+7+8+=20
5+15+=20
6+14+=20
7+13+=20
8+12+=20
9+11+=20
可能大家还是不太明白是怎么一回事吧?递归理解好了问题就解决了!
首先,大家先不用急,给你们看个下例子 再去理解上面的题目就好多了。
现在有个这样的情况:
public class Test1 {
static int count = 0;
static void show(){
for(int i=1;i<=10;i++){
count++;
if(count>1){System.out.println("count的值为:"+count);return;}
show();
System.out.println("LOL I love!");
}
}
public static void main(String[] args) {
show();
}
}
问控制台会输出什么?
输出的结果为:
count的值为:2
LOL I love!
count的值为:3
为什么会这样呢?大家跟我来分析流程。1.程序首先进入main方法调用show().
2.count的初始值为0,第一次show()方法中count变为了1->程序执行if下面的show()方法(此时暂时不会执行show下面的输出语句)。程序重新执行show方法,因为count是全局变量,因此 此时的count变为2(大家请注意 for循环里面的 i 的值并未 为2,还是从1开始。因为递归的各个局部变量是保存在堆栈里面的)。3.此时的count>1输出 count的值为:2,return后此次递归结束,返回结果给上一层。此时继续执行步骤2中中断的路程(也就是show下面的输出语句).此时输出 LOL
I love!(大家注意count是全局变量,现在仍未2 )因为此时的i=1,因此会在执行一次循环,输出结果为 count的值为:3
比较简洁的描述为:
1.count = 0 ,show()开始执行,count = 1。
2.递归调用show() ,count = 2,输出 count的值为:2,此时 i=1。
3.第二个show()执行遇到结束条件 return;返回上一层的状态
4.执行第一次show下面的输出方法 输出 LOL I love!
5.第一层状态的 i 也为1(<10),count = 3 ,输出 count的值为:3,递归结束(此时不会执行下面的show方法了,因为递归是先从上往下调用,然后从下往上返回结果,重新返回到第一层状态时候递归就结束了,这点大家可能不是很好理解。)
因此,了解了递归,就可以轻松了解1~19中组成20数字的递归解法了。程序运行是这样的顺序
1.arrayIndex初始值为0 array[arrayIndex]=1<20
2..arrayIndex++
array[0~arrayIndex]=1+23<20 .......arrayIndex
= 5 array[0~5]=1+2+3+4+5+6=22>20 此时一共调用了6层方法,因为22>20,所以第六层递归满足结束的条件。于是第五个加数就不存在了,第四个加数加1(没掉一层combination方法,加数就增加一个).以此类推
3.展示第一个结果
①.1+2+3+4+5+6=22>20--->②.1+2+3+4+6=21>20----->③.1+2+3+4+7<20......1+2+3+4+10=20.第四层递归结束
相关文章推荐
- AIX-maxuproc参数案例
- 2.7 Intersection
- kX3552 + HiFi级播放器 + wifi无线保真= 实战HiFi音乐娱乐欣赏
- SVN:冲突解决 合并别人的修改zz
- 使用ANT打包Android应用
- 2.6 Palindrome
- Android 实现调整屏幕亮度,以及自动适应
- 利用命令提示符转换硬盘模式
- 2.5 Sum List
- 如何在Webstorm/Phpstorm中设置连接FTP,并快速进行文件比较,上传下载,同步等操作(远程开发)
- *LeetCode-House Robber II
- Product of Array Except Self - LeetCode
- Android WebView详解
- 在线升级FlashPlayer和GoogleChrome的bash脚本
- 在线升级FlashPlayer和GoogleChrome的bash脚本
- *LeetCode-Number of Digit One
- Note:except和except for的区别
- Wireshark学习笔记——如何快速抓取HTTP数据包
- wireshark 抓包分析 TCPIP协议的握手
- TCP/IP协议分析