• 组合数计算-java


    排列组合是计算应用经常使用的算法,通常使用递归的方式计算,但是由于n!的过于大,暴力计算很不明智。一般使用以下两种方式计算。

    一,递归的思想:假设m中取n个数计算排列组合数,表示为comb(m,n)。那么comb(m,n)= comb(m-1,n-1)+comb(m-1,n)

    解释思想,从m个球中取出n个球可以分成两种情况相加,从m个球中取出一个球,如果它属于n,还需要从m-1中取出n-1个球;如果它不属于n,则需要从m-1中取出n个球

    根据这种思想可以通过递归的思想计算组合数:

    private static long comb(int m,int n){if(n==0)
                return 1;
            if (n==1) 
                return m;
            if(n>m/2)
                return comb(m,m-n);
            if(n>1)
                return comb(m-1,n-1)+comb(m-1,n);  
        
    return -1; //通过编译需要,数字无实际意义
    }

    适用递归计算,当数字较大时,递归深度过深,会相对耗时,甚至堆栈溢出。如果对性能有要求,可以建立键-值对,存储计算结果,防止,反复计算。

    static Map<String,Long> map= new HashMap<String, Long>();
    private static long comb(int m,int n){
            String key= m+","+n;
            if(n==0)
                return 1;
            if (n==1) 
                return m;
            if(n>m/2)
                return comb(m,m-n);
            if(n>1){
                if(!map.containsKey(key))
                    map.put(key, comb(m-1,n-1)+comb(m-1,n));
                return map.get(key);
            }
            return -1;
        }

    二,对数的计算思想:跟据定义,comb(m,n)=m!/(m-n)!n!

    两边取对数,log(comb(m,n))=log(m!/n!)-log((m-n)!)

    计算之后,再通过exp计算最终结果。优点,不会出现数组越界,缺点:计算非常大的数字时,由于精度误差,结果转化为整数时可能有偏差

     private static double comb_log(int m,int n){
            int  i;
            if(n>m-n) n=m-n;
            double s1=0.0;
            double s2=0.0;
            for (int j = m-n+1; j <=m; j++) {
                s1+=Math.log(j);
            }
            for (int j = 1; j <=n; j++) {
             s2+=Math.log(j);
            }
            return Math.exp(s1-s2);
        }
    本博客所有内容为原创,转载需征求作者同意。
  • 相关阅读:
    关于grunt
    关于网页上标题图标显示
    form表单原理
    js判断是android访问还是ios访问
    判断客户端是手机访问还是电脑访问网站(php代码)
    电脑手机模拟器模拟手机浏览器,在线浏览手机网站
    手机网站通过JS判断是否为iPhone手机访问
    手机页面一键拨号
    html5手机网站常用的9个CSS属性
    js解析与序列化json数据(一)json.stringify()的基本用法
  • 原文地址:https://www.cnblogs.com/xueyudlut/p/9498275.html
Copyright © 2020-2023  润新知