返回
进击的刷题日记:征服公共祖先与最大连续bit数
后端
2024-02-16 10:22:10
最近公共祖先与求最大连续bit数刷题分享
在算法刷题的浩瀚海洋中,有两道经典题目浮出水面,成为众多算法爱好者的试金石:最近公共祖先(LCA)和求最大连续bit数。今天,我就来分享我的刷题心得,带你领略这两道题目的魅力。
最近公共祖先:寻找家族血脉的纽带
给定一棵树结构,树中的每个节点代表一个家族成员,节点之间的边代表亲子关系。最近公共祖先(LCA)问题要求我们找出两个给定节点的最近公共祖先,即它们在家族树中最近的共同祖先。
LCA问题的解决方法有很多,其中一种常用的方法是倍增法 。倍增法的核心思想是预处理出每个节点在 2^i 级祖先上的信息,然后通过二分查找的方式快速找出最近公共祖先。
求最大连续bit数:探寻二进制中的奥秘
最大连续bit数问题要求我们找出给定整数中连续 1 最多的个数。例如,对于整数 13(二进制表示为 1101),其最大连续bit数为 2(连续的两个 1)。
求最大连续bit数的算法十分巧妙。我们使用一个变量 max_consecutive
记录当前连续 1 的个数,并遍历整数的每一位。如果当前位为 1,则 max_consecutive
加 1;否则,将 max_consecutive
重置为 0。最终,max_consecutive
的最大值就是所求的最大连续bit数。
附录:Java 代码实现
最近公共祖先(倍增法):
public class LCA {
private int[][] anc; // 2^i 级祖先
private int[] depth; // 节点深度
private int[] log; // log2
public LCA(int[][] adj, int n) {
anc = new int[log[n]][n];
depth = new int[n];
log = new int[n + 1];
dfs(1, 1, 0, adj);
preProcess(adj, n);
}
public int lca(int u, int v) {
if (depth[u] < depth[v]) {
int temp = u;
u = v;
v = temp;
}
int diff = depth[u] - depth[v];
for (int i = log[diff]; i >= 0; i--) {
if ((diff & (1 << i)) != 0) {
u = anc[i][u];
}
}
if (u == v) {
return u;
}
for (int i = log[n] - 1; i >= 0; i--) {
if (anc[i][u] != anc[i][v]) {
u = anc[i][u];
v = anc[i][v];
}
}
return anc[0][u];
}
private void dfs(int u, int p, int d, int[][] adj) {
anc[0][u] = p;
depth[u] = d;
for (int v : adj[u]) {
if (v != p) {
dfs(v, u, d + 1, adj);
}
}
}
private void preProcess(int[][] adj, int n) {
for (int i = 1; i < log[n]; i++) {
for (int j = 1; j <= n; j++) {
anc[i][j] = anc[i - 1][anc[i - 1][j]];
}
}
}
}
求最大连续bit数:
public class MaxConsecutiveBit {
public int maxConsecutiveBit(int n) {
int max_consecutive = 0;
int current_consecutive = 0;
while (n != 0) {
if ((n & 1) == 1) {
current_consecutive++;
} else {
current_consecutive = 0;
}
max_consecutive = Math.max(max_consecutive, current_consecutive);
n >>= 1;
}
return max_consecutive;
}
}