常用小算法
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) )推理
样 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)
(这里很重要!!具体请参阅秦九韶算法: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 )
当然由算法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算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
5.求二叉树高度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public int getDepth(TreeNode node) { if (node == null) return 0; else return Math.max(getDepth(node.left),getDepth(node.right)) + 1; }