返回

进击的刷题日记:征服公共祖先与最大连续bit数

后端

最近公共祖先与求最大连续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;
    }
}