【问题标题】:Check if two arrays are cyclic permutations检查两个数组是否是循环排列
【发布时间】:2017-03-03 18:32:24
【问题描述】:

给定两个数组,如何检查一个是否是另一个的循环置换?

例如,给定 a = [1, 2, 3, 1, 5]b = [3, 1, 5, 1, 2]c = [2, 1, 3, 1, 5],我们有 ab 是循环排列,但 c 不是其中任何一个的循环排列。

注意:数组可能有重复的元素。

【问题讨论】:

标签: algorithm language-agnostic cycle permutation


【解决方案1】:

这里的标准技巧是将其中一个数组与其自身连接起来,然后尝试在连接后的数组中找到第二个数组。

例如,'a' 与自身连接是:

[1, 2, 3, 1, 5, 1, 2, 3, 1, 5]

由于您确实在此数组中从第三个元素开始看到“b”,因此 a 和 b 是循环排列。

【讨论】:

  • 我假设您假设数组的长度相同。即便如此,为什么不可能有误报?
  • 是的。如果数组的长度不相等,那么它们就不是彼此的排列。
  • 如果算法说它是一个排列,它将是构造。如果您确实在位置 ai 的 'a' +'a' 中找到了 'b',那么如果将 'a' 移动 i 以使 ai 是 'a' 的第一个元素,则环绕将恰好是第二个部分您匹配的串联数组的“a”。
  • 这就是证据。如果它们是彼此的循环排列,该算法会准确告诉您将“a”移动多少才能得到“b”。
【解决方案2】:

如果 A 和 B 是彼此的循环排列,则 A 将在双重列表 BB 中找到(就像 B 在 AA 中一样)。

【讨论】:

    【解决方案3】:

    处理大量数据的有效方法是将它们中的每一个转换为“规范”形式,然后比较它们是否相等。对于这个问题,您可以选择“排序最小”的一个作为所有旋转排列的规范形式。

    所以 'a' 和 'b' 的规范形式是 [1, 2, 3, 1, 5],它们是相等的,所以它们是非循环排列。

    'c' 的规范形式是 [1, 3, 1, 5, 2],这是不同的。

    【讨论】:

    • 我喜欢这个算法。它为什么起作用是直观的。你能解释一下当有重复元素时如何找到规范形式(例如ab中的1)?
    • 将条目视为字母,将排列视为单词。 “单词” 12315 在 15123 之前排序,因此它是最小的,即规范的。
    • 我明白了。所以找到规范表示需要O(n^2) 元素比较,其中n 是数组的长度?即:循环遍历所有n可能的旋转保持当前最小值,并且对于每个旋转,执行O(n)比较以确定是否更新最小值。也许有更好的方法..
    • @dsg 如果您有 n 个要比较的数组,请考虑比较次数,例如“大量数据”。
    • 以防万一,这对您来说还不够清楚。拥有规范形式意味着您可以散列值以加快比较速度。
    【解决方案4】:

    这是一种简单的临时方法,用于找出具有 O(n) 时间复杂度的循环排列。

    a = [1, 2, 3, 1, 5], b = [3, 1, 5, 1, 2]

    在 a[] 中找到 b[0] 的索引,假设索引是 'x'。然后开始 在两个数组中导航。 a[] 从索引 'x' 和 b[] 开始 从“0”开始。这样它们两个必须具有相同的值。如果 不,它们不是循环的。 这是示例代码。

     public class CyclicPermutation {
    
        static char[] arr = { 'A', 'B', 'C', 'D' };
        static char[] brr = { 'C', 'D', 'K', 'B' };
        boolean dec = false;
    
        public static void main(String[] args) {
            boolean avail = true;
            int val = getFirstElementIndex(brr[0]);
            if(val ==Integer.MIN_VALUE){
                avail = false; 
                return;
                }
    
            for (int i = val, j = 0; j <= brr.length-1; ) {
                if (i > arr.length-1) {
                    i = 0;
                }
                if (arr[i] == brr[j]) {
                    i++;
    
                    j++;
    
                } else {
                    avail = false;
                    System.out.println(avail);
                    return;
                }
    
    
            }
    
       System.out.println(avail);
        }
    
        public static int getFirstElementIndex(char c) {
    
            for (int i = 0; i <= arr.length; i++) {
                if (arr[i] == c) {
                    return i;
                }
            }
            return Integer.MIN_VALUE;
        }
    
    
    }
    

    【讨论】:

    • 这不起作用,因为同一个字符可以在一个数组中出现多次
    猜你喜欢
    • 2015-09-14
    • 2017-04-08
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2021-12-29
    • 1970-01-01
    相关资源
    最近更新 更多