亲宝软件园·资讯

展开

Java C++ 可能的二分法

AnjaVon 人气:0

题目要求

思路一:反向点+并查集

下面浅学一些并查集的基本概念,然后再去实现思路——

浅学并查集(Union Find)

学习参考链接

简介:

一种树型的数据结构,用于处理一些不相交集合的合并查询问题;

基础操作:

通常包括三个函数

函数功能
find(x)查找元素xxx属于哪个集合,也就是找当前元素所在树的根节点,查找的同时进行路径压缩
union(a, b)合并元素aaa和元素bbb所属集合,根据树高合并两棵树
isConnected(a, b)判断aaa和元素bbb是否处于同一集合中,也就是判断二者根是否相同

Java

class Solution {
    int[] p = new int[4010]; // 并查集数组,存父级节点
    // 找当前节点的根
    int find(int x) {
        if(p[x] != x) // 非根节点
            p[x] = find(p[x]); // 继续向下找根并进行路径压缩
        return p[x];
    }
    // 连接两节点的根
    void union(int a, int b) {
        p[find(a)] = p[find(b)];
    }
    // 两节点是否连通
    boolean isConnected(int a, int b) {
        return find(a) == find(b);
    }
    public boolean possibleBipartition(int n, int[][] dislikes) {
        for (int i = 1; i <= 2 * n; i++) // 节点+反向节点
            p[i] = i; // 初始化并查集,指向自己
        for (int[] cur : dislikes) {
            int a = cur[0], b = cur[1];
            if (isConnected(a, b)) // 连通,被迫在一组
                return false;
            // 利用反向节点维护连通关系
            union(a, b + n);
            union(b, a + n);
        }
        return true;
    }
}

C++

class Solution {
public:
    int p[4010]; // 并查集数组,存父级节点
    // 找当前节点的根
    int find(int x) {
        if(p[x] != x) // 非根节点
            p[x] = find(p[x]); // 继续向下找根并进行路径压缩
        return p[x];
    }
    // 连接两节点的根
    void unionn(int a, int b) {
        p[find(a)] = p[find(b)];
    }
    // 两节点是否连通
    bool isConnected(int a, int b) {
        return find(a) == find(b);
    }
    bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
        for (int i = 1; i <= 2 * n; i++) // 节点+反向节点
            p[i] = i; // 初始化并查集,指向自己
        for (auto cur : dislikes) {
            int a = cur[0], b = cur[1];
            if (isConnected(a, b)) // 连通,被迫在一组
                return false;
            // 利用反向节点维护连通关系
            unionn(a, b + n);
            unionn(b, a + n);
        }
        return true;
    }
};

思路二:染色法

Java

class Solution {
    int N = 2010, M = 2 * 10010;
    int[] head = new int[N], edge = new int[M], next = new int[M];
    int[] color = new int[N];
    int idx = 0;;
    void add(int a, int b) {
        edge[idx] = b;
        next[idx] = head[a];
        head[a] = idx++;
    }
    boolean DFS(int node, int clr) {
        color[node] = clr;
        for (int i = head[node]; i != -1; i = next[i]) {
            int j = edge[i];
             // 不喜欢双方同色
            if (color[j] == clr)
                return false;
            if (color[j] == 0 && !DFS(j, 3 - clr))
                return false;
        }
        return true;
    }
    public boolean possibleBipartition(int n, int[][] dislikes) {
        Arrays.fill(head, -1);
        for (int[] cur : dislikes) { // 构建无向图
            int a = cur[0], b = cur[1];
            add(a, b);
            add(b, a);
        }
        for (int i = 1; i <= n; i++) {
            if (color[i] != 0) // 已经染过
                continue;
            if (!DFS(i, 1)) // 无法染色成功
                return false;
        }
        return true;
    }
}

C++

class Solution {
public:
    static const int N = 2010, M = 2 * 10010;
    int head[N], edge[M], next[M];
    int color[N];
    int idx = 0;;
    void add(int a, int b) {
        edge[idx] = b;
        next[idx] = head[a];
        head[a] = idx++;
    }
    bool DFS(int node, int clr) {
        color[node] = clr;
        for (int i = head[node]; i != -1; i = next[i]) {
            int j = edge[i];
             // 不喜欢双方同色
            if (color[j] == clr)
                return false;
            if (color[j] == 0 && !DFS(j, 3 - clr))
                return false;
        }
        return true;
    }
    bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
        memset(head, -1, sizeof(head));
        for (auto cur : dislikes) { // 构建无向图
            int a = cur[0], b = cur[1];
            add(a, b);
            add(b, a);
        }
        for (int i = 1; i <= n; i++) {
            if (color[i] != 0) // 已经染过
                continue;
            if (!DFS(i, 1)) // 无法染色成功
                return false;
        }
        return true;
    }
};

总结

算法题就回避一下Rust……待我学成归来……

填了拖了好久的并查集的坑还捎带复习了一波链式前向星存图;

感觉链式前向星忘得差不多了……

加载全部内容

相关教程
猜你喜欢
用户评论