降低无向图的时间复杂度

问题描述 投票:0回答:1

我有一个无向图,表示 Facebook 等社交媒体中的用户连接。 有N个节点,从1到N 边由数组 from 和 to 表示。 任务数组表示我有兴趣查找该节点(即社交媒体中的用户)的连接的节点号。

示例:

N = 5
From = [2,2,1,1]
To = [1,3,3,4]
Task = [4,2,5]

答案:

[4,4,1]

说明:

图表如下所示:

Now for Task [4,2,5]

4 -> [1,2,3,4] The node 4 has these connections 
2 -> [1,2,3,4] The node 2 has these connections 
5 -> [5]

所以结果是[4,4,1]

限制:

N=2 to 10^5
size of arrays from, 'to', and tasks is 2 to 10^5

这是一个黑客级别的问题。我的代码在 15 个测试用例中有 8 个失败,表示大输入出现超时错误。

这是我的代码:

public static List<Integer> solve(int N, List<Integer> from, List<Integer> to, List<Integer> tasks) {
    int n = from.size();
    // Create the graph
    Map<Integer, Set<Integer>> map = new HashMap<>();
    for(int i=0; i<n; i++) {
        int key1 = from.get(i);
        int key2 = to.get(i);
        
        Set<Integer> value = map.getOrDefault(key1, new HashSet<>());
        value.add(key2);
        map.put(key1, value);
        
        value = map.getOrDefault(key2, new HashSet<>());
        value.add(key1);
        map.put(key2, value);       
    }
    List<Integer> result = new ArrayList<>();
    for(int node: tasks) {
        result.add(bfs(map, node));
    }
    return result;
}
    // Solve using breadth first search approach
public static int bfs(Map<Integer, Set<Integer>> map, int node) {
    Set<Integer> visited = new HashSet<>();
    Queue<Integer> q = new LinkedList<>();
    int count = 0;
    visited.add(node);
    q.add(node);
    while(!q.isEmpty()) {
        node = q.poll();
        count++;
        Set<Integer> val = map.get(node);
        if(val != null) {
            for(int next : val) {
                if(visited.add(next)) {
                    q.add(next);
                }
            }
        }
    }
    return count;
}

我也尝试了递归方法,仍然是同样的问题,对于大输入大小值,我遇到超时错误。

如何降低这段代码的时间复杂度。

java algorithm time-complexity breadth-first-search
1个回答
0
投票

当输入较大时,BFS 算法将一遍又一遍地在同一图组件上运行,始终得出相同的节点数。这是一个遗憾。

您可以创建一个不相交集,而不是创建不相交集知道节点所属的组件,并且可以在填充结构时跟踪组件的大小。

有几种替代算法可以合并两个组件。一次是“按大小联合”,这在这里似乎很合适,因为我们对大小感兴趣。

这是

DisjointSets
类的可能实现:

import java.util.*;

class DisjointSets<T> {
    private class Node {
        Node parent;
        int size;
        T key;

        Node(T key) {
            this.key = key;
            this.size = 1;  // The node starts as its own component
            this.parent = this;
        }
    }

    Map<T, Node> nodes = new HashMap<>();

    private Node find(T key) {
        Node node = nodes.computeIfAbsent(key, Node::new);
        while (node.parent != node) {
            node = node.parent = node.parent.parent; // Path halving
        }
        return node;
    }

    public void union(T keyA, T keyB) {
        Node nodeA = find(keyA);
        Node nodeB = find(keyB);
        if (nodeA == nodeB) return; // Already in same set
        if (nodeA.size < nodeB.size) {
            nodeA.parent = nodeB;
            nodeB.size += nodeA.size;
        } else {
            nodeB.parent = nodeA;
            nodeA.size += nodeB.size;
        }
    }

    public int size(T key) {
        return find(key).size;
    }
}

solve
函数可以是:

    public static List<Integer> solve(int N, List<Integer> from, List<Integer> to, List<Integer> tasks) {
        int n = from.size();
        DisjointSets<Integer> set = new DisjointSets<>();
        for (int i = 0; i < n; i++) {
            set.union(from.get(i), to.get(i)); // populate disjoint sets
        }
        List<Integer> result = new ArrayList<>();
        for (int node : tasks) {
            result.add(set.size(node));
        }
        return result;
    }
© www.soinside.com 2019 - 2024. All rights reserved.