- 之前面试遇到一个面试官,问了我一些Android基础的知识,然后就出了两个算法题目给我:
- 第一个,怎么使用
Java
中String
类的split()
方法。
- 这个就不多说了,当时我也磕磕碰碰的写出来了,写出来之后,一直让我优化,搞得我大为恼火,以为是故意折腾人的。
- 然后是一道纯粹的算法题目:有A-Z共26个字母,
A
是一种组合,B
是一种组合,AB
也是一种组合,ABC
也是,XDC
也是一种组合,以此类推。请使用代码实现,计算A-Z这26个字母的全部组合。
- 这一题就惨了,当时本来就很恼火了,因为之前的
String.split()
一直优化的问题。现在又搞这个,真是头都大了,不知道如何去解。我想了十几分钟,然后就告诉面试官,这个真不会,然后我就挂了。 - 今天忽然想到,这一题貌似可以使用找规律的方式去解决,于是写了一下:
- 这一题就惨了,当时本来就很恼火了,因为之前的
- 第一个,怎么使用
26个字母的排列组合的计算:
解:
1. 如果是1个字母A,则,组合数量sum = 1; (A)
2. 如果是2个字母AB,则,组合数量sum = 4; (A,B,AB,BA)
3. 如果是3个字母ABC,则 组合数量sum = 15; (A,B,C,AB,AC,BA,BC,CA,CB,ABC,ACB,BAC,BCA,CAB,CBA)
4. 如果是4个字母ABCD,则 组合数量sum = ?; (A,B,C,D, AB,AC,AD, BA,BC,BD, CA,CB,CD, DA,DB,DC, ABC,ABD, ACB,ACD, ADB,ADC, BAC,BAD, BCA,BCD, BDA,BDC,...,ABCD,ABDC, ACBD,ACDB, ADBC,ADCB, )
n + (n-1) *n + (n-2)*(n-1) *(n) + (n-2)*(n-1)*(n)
n + (n-1) *n +
f(1) = 1;
f(2) = 4;
f(3) = 15;
f(n) = ?
//===================
f(1) = 1;
f(n) = n + (n-1) *n + (n-2)*(n-1) *(n) +(n-2)*(n-1)*(n);
f(x) = {
if(x==1) f(x) =1;
else
f(x) = n + (n-1) *n + (n-2)*(n-1) *(n) +(n-2)*(n-1)*(n);
}
f(2) = 2+1*2 =4;
f(3) = 3+2*3+1*2*3 * 2 = 3+6+6 = 15;
f(26) = 26+ 26*25+ 24*25*26 *2 = 31876;
如果以上算法正确,那么答案就是31876.
但是很不幸,以上的算法是错误的。
- 正确的做法如下:
n个字母,每次都是1个字母参与的排序:n
n个字母,每次都是2个字母参与的排序:n*(n-1) (AB,AC,AD,..,AZ; BA,BC,..,BZ)[第一个位置有n个可能,第二个位置有n-1]
n个字母,每次都是3个字母参与的排序:n*(n-1)*(n-2) (ABC,ABD,ABE,ABF,...,ABZ; ACB,ACD,ACE,...,ACZ;) [第一个位置有n个可能,第二个位置有n-1,第三个位置有n-2个可能]
....
n个字母,每次都是n-1个字母参与排序:n*(n-1)*(n-2)*...*(2)
n个字母,每次都是n-1个字母参与排序:n*(n-1)*(n-2)*...*(2)*(1)
而,全部的排序组合就是以上的相加:
Sum(n) = f(n)+f(n-1)+ f(n-2)+...+f(2)+f(1);
其中:f(n) = n*(n-1)*(n-2)*..(1);
以上是算法,则代码为:(Java 实现:)
package com.pythonCat.sort;
import java.math.BigInteger;
/**
* Created by pythonCat on 16-2-23.
* 26个字母的任意排列组合的计算
*/
public class AbcSort {
public static void main(String[] args) {
AbcSort obj = new AbcSort();
long n = 26;
BigInteger count = obj.getSortCount(n);
System.out.println("n = " + n + ", sortCount = " + count);
BigInteger sortSum = obj.getSortSum(n);
System.out.println("n = " + n + ", sortSum = " + sortSum);
}
/**
* 获取n个不同字母A-Z全排列的所有组合
* n个字母,每次都是n个字母参与排序:n*(n-1)*(n-2)*...*(2)*(1)
*
* @param n n个字母
* @return
*/
public BigInteger getSortCount(long n) {
if (n == 1) return BigInteger.valueOf(1);//递归终止条件
else
return BigInteger.valueOf(n).multiply(getSortCount(n-1));//递归原则
}
/**
* 获取n个不同字母A-Z任意排列的所有组合
*
* @param n n个字母
* @return
*/
public BigInteger getSortSum(long n) {
BigInteger sum = BigInteger.valueOf(0);
while (n > 0) {
sum = sum.add(getSortCount(n));
n--;
}
return sum;
}
}
- 因为上面的排序结果太大,超出了long的范围,所以使用了
java.math.BigInteger
类,关于此类的介绍,请参阅API或这篇博客。 - 计算结果为(26个字母的任意排序的可能–控制台输出的结果):
n = 26, sortCount = 403291461126605635584000000
n = 26, sortSum = 419450149241406189412940313
以上就是这个问题的最终答案。