常用小算法

1.快速幂取模

要求 a^b % c的时候,当然可以直接循环然后每一步都mod c,这样的复杂度就是O(b)了,但是快速模取幂算法可以降低复杂度。

描述如下:

  可以把b按二进制展开为:b = p(n)*2^n  +  p(n-1)*2^(n-1)  +…+   p(1)*2  +  p(0)

  其中p(i) (0<=i<=n)为 0 或 1

  样 a^b =  a^ (p(n)*2^n  +  p(n-1)*2^(n-1)  +...+  p(1)*2  +  p(0))
               =  a^(p(n)*2^n)  *  a^(p(n-1)*2^(n-1))  *...*  a^(p(1)*2)  *  a^p(0)
  对于p(i)=0的情况, a^(p(i) * 2^(i-1) ) =  a^0  =  1,不用处理
  我们要考虑的仅仅是p(i)=1的情况
  化简:a^(p(i)*2^i)  = a^(p(i)*2^(i-1)  * 2) = (a^(  p(i)  *  2^(i-1) ) )^2    可由(   (a^b)^c = a^(b*c)   )推理 
  p(i) = 1
    所以a^(2^i) = (a^(2^(i - 1)))^2
  (这里很重要!!具体请参阅秦九韶算法:http://baike.baidu.com/view/1431260.htm
  利用这一点,我们可以递推地算出所有的a^(2^i)
  当然由算法1的结论,我们加上取模运算:
  a^(2^i)%c = ( (a^(2^(i-1)) % c ) * ( a^(2^(i-1)) % c ) 
下面是求 x^n % mod

 

    //快速模取幂算法
    private static long mod_pow(long x, long n, long mod) {
        long res = 1;
        while(n > 0) {
            if((n & 1) != 0) res = res * x % mod;
            x = x * x % mod;
            n >>= 1;
        }
        return res;
    }

2.判断素数

    public boolean isPrime(int n) {
        if (n < 2)
            return false;
        int k = (int)Math.sqrt(n);
        for (int i = 2; i <= k; i++) {
            if (n % i == 0)
                return false;
        }
        return true;
    }

 3.java中在涉及到字符串的增删改查操作时,尽量用StringBuffer。

4.kmp算法

    public boolean kmp(String par, String ori) {
        int next[] = new int[par.length()+1];
        //求next数组每个元素值
                    
        next[0] = -1;
        int k = -1, j = 0;
        while ( j < par.length()) {
            //k == -1就表示比较到了第一位还不相等,所以next[j] = 0
            //k其实就是next[j-1](k == -1时其实也是),par.charAt(j) == par.charAt(k)满足的话,也就是说next[j] = next[j-1]+1
            //如果不满足那就要从前k个字符的前缀不相等的那一位开始
            if (k == -1 || par.charAt(j) == par.charAt(k)) {
                next[++j] = ++k;//也就是说next[j] = next[j-1]+1
            } else {
                k = next[k];//从前k个字符的前缀不相等的那一位开始从新比较
            }
        }
        //            nextArray(par,next);
        int p = 0, q = 0;
        while (p < ori.length()) {
            if (par.charAt(q) == ori.charAt(p)) {
                if (q == par.length()-1) {
                    q = next[q];
                    return true;
                } else { //相等则继续往后比较
                    p++;
                    q++;
                }
            } else { //不相等则移动
                q = next[q];
            }
            if (q == -1) { //比较了模式串的第一个字符且不相等
                p++;
                q++;
            }
        }
        return false;
    }
View Code

 5.求二叉树高度

    public int getDepth(TreeNode node) {
        if (node == null)
            return 0;
        else 
            return Math.max(getDepth(node.left),getDepth(node.right)) + 1; 
    }
View Code

 

posted @ 2016-05-16 11:30  fisherinbox  阅读(183)  评论(0编辑  收藏  举报