面试趣闻,随记

  • 之前面试遇到一个面试官,问了我一些Android基础的知识,然后就出了两个算法题目给我:
    • 第一个,怎么使用JavaString类的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

以上就是这个问题的最终答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值