地图缩减算法

时间:2013-04-18 04:13:44

标签: java list map

我如何reduce Map<Integer, List<Integer>>

reduce'd地图成为Integer List<Integer>的每个 0 --> (0) 1 --> (1, 2) 2 --> (2, 1) 值唯一且不重复的地图。

示例:

地图A:

 0 --> (0)
 1 --> (1, 2)

会减少到:

 0 --> (0)
 2 --> (2, 1)

reduced

请注意,删除键1或2是可以接受的,因为它会生成0 --> 0映射。

编辑:当元素映射到自身时,它应该保持独立,例如{{1}}。但是,当多个值具有共同的Integer时,它们应该合并。

3 个答案:

答案 0 :(得分:1)

试试这个

class ReducedMap extends HashMap<Integer, List<Integer>> {
    private Set<Set<Integer>> set = new HashSet<Set<Integer>>();

    @Override
    public List<Integer> put(Integer key, List<Integer> value) {
        Set<Integer> set = new HashSet<Integer>(value);
        if (!this.set.add(set)) {
            return new ArrayList<Integer>(set);
        }
        return super.put(key, value);
    }
      ...

答案 1 :(得分:0)

保留一个ArrayList,让我们调用它&#34;合并&#34;。

您应该使用HashSet来检测重复值。检查一个元素(列表中的值)是否在HashSet中,如果是,则忽略它,否则将其放入HashSet并将其添加到&#34; merged&#34; ArrayList中。

显然,您必须在此逻辑的开头添加一个案例,以便不考虑元素是否映射到自身。

算法如下所示:

  1. 声明地图&gt;叫&#34; ret&#34;和一个叫做#34的ArrayList合并&#34;和一个名为&#34; duplicate_checker&#34;

  2. 的HashSet
  3. 对于输入地图中的每个列表

    2.1如果它映射到自身,则将其放入&#34; ret&#34;

    2.2否则,对于当前列表中的每个元素,如果它不在&#34; duplicate_checker&#34;然后将其添加到&#34;合并&#34;

  4. Put&#34;合并&#34;到&#34; ret&#34;

  5. 返回&#34; ret&#34;
  6. 希望这有帮助。

答案 2 :(得分:0)

这样的事情应该有效。

版本#2,第一个有错误

我会使用配对类,因为我们要从地图中提取所有条目并将它们放在配对的矢量中。

private static class Pair {

    public Pair(Integer k, List<Integer> l) {

        this.k = k;
        this.s = new HashSet<Integer>();
        this.s.addAll(l);
    }

    public Integer k;
    public Set<Integer> s;
}

接下来,我们需要一种方法来检查两个集合是否有一些共同的元素。

public static boolean intersect(Set<Integer> a, Set<Integer> b) {

    Set<Integer> tmp = new HashSet<Integer>(a);
    tmp.retainAll(b);

    return !tmp.isEmpty();
}

缩小方法采用地图并返回一个新的缩小地图。

public static Map<Integer, List<Integer>> reduce(Map<Integer, List<Integer>> m) {

首先我们将地图转换为的数组;这将允许有效的迭代和消除键。

    int cnt = 0;
    Pair[] entries = new Pair[m.size()];

    for (Integer k : m.keySet()) {

        List<Integer> l = m.get(k);
        entries[cnt] = new Pair(k, l);
        ++cnt;
    }

然后我们针对任何其他条目测试每个;如果他们有共同的元素,我们删除后者,但首先我们将它合并到前者。

    for (int i = 0; i < m.size(); ++i) {

        for (int j = i + 1; j < m.size(); ++j) {

            if (entries[i] != null && entries[j] != null && intersect(entries[i].s, entries[j].s)) {

                Set<Integer> si = entries[i].s;
                Set<Integer> sj = entries[j].s;

                si.addAll(sj);
                entries[j] = null;
            }
        }
    }

最后,我们将数组转换回地图,跳过已删除的元素。

    Map<Integer, List<Integer>> r = new HashMap<Integer, List<Integer>>();

    for (int i = 0; i < m.size(); ++i)
        if (entries[i] != null)
            r.put(entries[i].k, new ArrayList<Integer>(entries[i].s));

    return r;
}