查找数组是否为排列的最佳方法

时间:2018-12-05 20:56:24

标签: python python-3.x algorithm

给出了一个由A整数组成的非空数组N

排列是一个序列,包含从1到N的每个元素,每个元素恰好一次。 例如,[4,2,1,3] 是一个排列,但[4,1,3] 不是排列,因为缺少值2

目标是检查输入数组A是否是排列。

约束

  • N是[1..100,000]范围内的整数;
  • A的每个元素都是[1..1,000,000,000]范围内的整数。

我的代码:

# 1 = permutation 0 = not a permutation
def solution(A):
    total = sum(A)

    formula_total = (len(A)*(len(A)+1))/(2)

    if total == formula_total:

        return 1

    return 0

我的解决方案在Antisum上失败(我不知道那是什么)

4 个答案:

答案 0 :(得分:4)

然后,您可以检查列表的最小值是否为1,最大值是否等于列表的长度。然后,您可以将列表转换为集合,以检查长度是否相等,如果相等,则列表中的所有项目都是唯一的,因此该列表就是您认为的排列方式:

def solution(A):
    return min(A) == 1 and max(A) == len(A) == len(set(A))

这样:

print(solution([4,2,1,3]))
print(solution([4,1,3]))
print(solution([4,2,1,4]))
print(solution([4,2,5,3]))

输出:

True
False
False
False

如果您希望将10作为返回值,则可以将布尔值传递给int()构造函数:

def solution(A):
    return int(min(A) == 1 and max(A) == len(A) == len(set(A)))

答案 1 :(得分:3)

这只是七巧板问题的一个版本。对输入数组进行排序。与元素1到N的数组比较是否相等。返回该比较的布尔结果。

如果需要线性解,请声明seen,它是大小为N的布尔数组。迭代输入数组。在处理元素时对它们进行计数。

对于每个元素A

  • 如果A不在1-N范围内返回失败
  • 如果seen[A]返回失败
  • seen[A] =真

最后,返回count == N。换句话说,如果为count == N,我们发现每个整数之一;返回True。否则,返回False(在这种情况下,计数将小于N)。

答案 2 :(得分:1)

def getMax(A):
    max_ele = 0
    for each_integer in A:
        max_ele = max(max_ele,each_integer)
    return max_ele

def restoreArray(A):
    for idx, val in enumerate(A):
        A[idx] = abs(A[idx])

def solution(A):
    max_ele = getMax(A)
    if len(A) != max_ele:
        return False
    for idx, val in enumerate(A):
        if A[abs(A[idx]) - 1] < 0:
            # restore the array back   
            restoreArray(A)
            return False
        else:
            A[abs(A[idx]) - 1] = -A[abs(A[idx]) - 1]

    # restore the array back   
    restoreArray(A)
    return True


print(solution([4,2,1,3]))
print(solution([4,1,3]))
print(solution([4,2,1,4]))
print(solution([4,2,5,3]))
print(solution([1,2,3,4]))
print(solution([1,2,3,4,6,7,2]))
print(solution([9,2,3,4,6,7,5,8,1]))
print(solution([9,2,3,4,6,7,5,8,1,10,6]))

输出:

True
False
False
False
True
False
True
False

算法:

  • 我们可以利用所有元素都是正数的约束。
  • 因此,我们在数组上循环并通过使特定索引处的整数为负来将索引标记为已访问。
  • 现在,如果遇到一个索引,该索引指向另一个已经为负的索引,则返回False
  • 如果我们从没有遇到过这种情况,那肯定是一个排列,然后我们返回True
  • 我们确实将阵列还原了,所以我们不会对其进行修改。
  • 时间复杂度: O(n),空间复杂度: O(1)
  • 您可以使该解决方案更具pythonic的特性(因为我不是python爱好者),因此我将留给您练习。

答案 3 :(得分:0)

这里的禁食解决方案是

import numpy as np

# create integer array `data`

seen = np.zeros(len(data), dtype=bool)
seen[data] = True
is_permutation = np.all(seen)

as suggested by @Prune。 sort-and-compare-with-arange 建议慢了大约 20 倍。

enter image description here


重现情节的代码:

import numpy as np
import perfplot


def setup(n):
    return np.random.permutation(np.arange(n))


def sort(data):
    return np.sort(data) == np.arange(len(data))


def seen(data):
    seen = np.zeros(len(data), dtype=bool)
    seen[data] = True
    return np.all(seen)


def min_max_set(data):
    return min(data) == 0 and max(data) + 1 == len(data) == len(set(data))


b = perfplot.bench(
    setup=setup,
    kernels=[sort, seen, min_max_set],
    n_range=[2 ** k for k in range(23)],
    xlabel="len(array)",
)
b.save("out.png")
b.show()