另类加法 🔗
思路:不能使用算术运算符那就只能用位运算符
二进制加法的逻辑如下
1.上下不同,一个0一个1,结果为0+1=1,异或运算可以满足
2.上下同为0, 结果为0, 异或也运算可以满足
3.上下同为1, 若还是使用异或, 结果变成0,与期望不相符合, 想办法弥补了这点就好了. 研究发现, 1+1的结果应该是10,相当于按位与后左移一位
综上,x+y可以通过x^y + (x&y)<<1实现, 这中间的+就递归实现
public int addAB(int A, int B) {
if (A == 0) {
return B;
} else if (B == 0) {
return A;
} else {
return addAB(A^B, (A&B) << 1);
}
}
走方格的方案数 🔗
递归法思路:
把每个点都当作是一个出发点, 若该点坐标为(m,n), 该点出发的方案数是(m-1,n)的方案数和(m,n-1)的方案数的和.
递归终止条件是,当m或者n走到头了,就只有一个方向可以走, 相当于只有一种方案了, 返回1.
public static int getPlans (int m, int n) {
if (m == 0 || n == 0) {
return 1;
}
return getPlans(m - 1, n) + getPlans(m, n - 1);
}
最近公共祖先 🔗
自下而上思路:
自下而上找, 不断向上找父节点, 相等即返回
public static int getLCA (int a, int b) {
while (a != b) {
while (a < b) {
b /= 2;
}
while (a > b) {
a /= 2;
}
}
return a;
}
自上而下思路:
只由编号定义的二叉树, 只能从编号的大小关系上去研究.
首先我们先把每种情况都列举出来:
1.子树在根结点的两边;
2.子树在根结点的左边;
3.子树在根结点的右边;
4.其中一个子树是根结点;
判断逻辑:
1.其中一个子树是根结点:返回根结点编号
2.子树在根结点左右两边:返回根结点编号
3.子树在根结点同侧:进入下一次递归.
import java.util.*;
public class LCA {
public int getLCA(int a, int b) {
return getLCA(1, a, b);
}
public static int getLCA (int root, int a, int b) {
if (root == a|| root == b) {
return root;
}
//获取a在左边还是右边
int edge = root * 2 + 2;
int aLevel = 2;
while (edge < a) {
edge = edge * 2;
aLevel++;
} //循环结束后a < edge
boolean aAtRight = false;
if (a > edge - aLevel) {
aAtRight = true;
}
//获取b在左边还是右边
edge = root * 2 + 2;
int bLevel = 2;
while (edge < b) {
edge = edge * 2;
bLevel++;
} //循环结束后a < edge
boolean bAtRight = false;
if (b > edge - bLevel) {
bAtRight = true;
}
//a b在异侧, 返回root
if (bAtRight && !aAtRight || !bAtRight && aAtRight) {
return root;
} else if (bAtRight && aAtRight) {
if (aLevel < bLevel) {
return a;
} else if (aLevel > bLevel) {
return b;
} else {
return getLCA(root * 2 + 1, a, b);
}
} else {
if (aLevel < bLevel) {
return a;
} else if (aLevel > bLevel) {
return b;
} else {
return getLCA(root * 2, a, b);
}
}
}
}
这个代码的问题就在, 不能应对大数据的情况, 因为递归多, 且每次递归的时间复杂度也大, 会导致栈溢出.
查找组成一个偶数的两个最近素数 🔗
错误思路:
一个left从前找素数, 一个right从后找素数, 找到以后left和right就相加看看是否等于偶数n, 相等就记录下当前的left和right值, 然后left和right都+=2, 知道left >= right;
思路的bug: 20的最近素数组合是13和7, 但是按照上方法得到right为13时, left的值是5, 此时13+5!=20, 继续循环会使得13错过7, 最终没有正确结果.
另起思路:
将所有小于n的素数按大小存起来, 然后从遍历, 挨个相加, 这样不会错过每一个值.
幸运的袋子 🔗