【问题标题】:Given adjacency rules and unsorted array, return array conforming to rules给定邻接规则和未排序数组,返回符合规则的数组
【发布时间】:2019-12-15 16:03:57
【问题描述】:

假设我有一个包含一些字符和一组规则的数组:

char[] chars = new int[]{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' }; 
char[][] rules = { {'A', 'B'} , {'C', 'B'}, {'F', 'E'} }

chars 中的字符是不同的,rules 是在输出中必须相邻的字符对的二维数组。

我想返回一个数组,其中包含满足rules 中所有约束的chars 的所有元素。如果有多个可能的选项,则该数组应按字母顺序排列。保证至少有一种解决方案。

我将如何解决这个问题?我不太确定如何开始。

【问题讨论】:

  • 这里好像可以使用拓扑排序。你应该研究一下:geeksforgeeks.org/topological-sorting
  • 不是拓扑排序。拓扑排序不会对输出中的邻接性施加任何限制,只是相对顺序。
  • chars 中的字符一定是不同的吗?规则是否保证一致,即总是有解决方案?
  • @kaya3 是的,是的:chars 的所有元素都是不同的,并且始终存在解决方案。

标签: java arrays algorithm sorting constraints


【解决方案1】:

由于字符是不同的,并且每个字符在输出中只能出现在其他两个字符旁边,因此每个字符最多只能出现在两个规则中。如果我们将规则视为graph 中的边,那么它们会形成一组不相交的路径。

最早的按字母顺序排列的解决方案可以通过查找所有不在任何路径中或为路径端点的字符,然后按字母顺序将它们插入到输出中来形成。当插入路径端点时,我们必须在继续之前按顺序插入该路径的其余部分。

为了方便地找到具有零条或一条边的节点并沿路径迭代,我们首先将edge list data structure 转换为adjacency list data structure

import java.util.*;

public class Solution {
    public static char[] solve(char[] letters, char[][] rules) {
        // convert to adjacency list
        Map<Character, List<Character>> neighbours = new HashMap<>();
        for(char[] edge : rules) {
            char a = edge[0], b = edge[1];
            neighbours.computeIfAbsent(a, ArrayList::new).add(b);
            neighbours.computeIfAbsent(b, ArrayList::new).add(a);
        }

        // find nodes with 0 or 1 edges, in order
        List<Character> endpoints = new ArrayList<>();
        for(char a : letters) {
            if(!neighbours.containsKey(a) || neighbours.get(a).size() <= 1) {
                endpoints.add(a);
            }
        }
        Collections.sort(endpoints);

        // build output
        char[] out = new char[letters.length];
        Set<Character> used = new HashSet<>();
        int i = 0;
        for(char a : endpoints) {
            if(used.contains(a)) { continue; }
            out[i++] = a;
            used.add(a);
            // if it's a path, iterate along path
            while(neighbours.containsKey(a) && !neighbours.get(a).isEmpty()) {
                char b = neighbours.get(a).get(0);
                out[i++] = b;
                used.add(b);
                // remove previous neighbour so next one guaranteed at index 0
                neighbours.get(b).remove((Character) a); // don't convert to int
                a = b;
            }
        }
        return out;
    }
}

例子:

>>> Solution.solve(
...     new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' },
...     new char[][] { {'A', 'B'} , {'D', 'B'}, {'G', 'E'}, {'H', 'A'} }
... )
... 
char[8] { 'C', 'D', 'B', 'A', 'H', 'E', 'G', 'F' }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2016-12-06
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 2012-05-19
    相关资源
    最近更新 更多