How to tell if an array is a permutation in O(n)?

后端 未结 16 1596
粉色の甜心
粉色の甜心 2020-12-07 10:17

Input: A read-only array of N elements containing integer values from 1 to N (some integer values can appear more than once!). And a memory zone of a fixed<

相关标签:
16条回答
  • 2020-12-07 10:32

    I doubt you would be able to prove that ;)

      (1, 2, 4, 4, 4, 5, 7, 9, 9)
    

    I think that more generally, this problem isn't solvable by processing the numbers in order. Suppose you are processing the elements in order and you are halfway the array. Now the state of your program has to somehow reflect which numbers you've encountered so far. This requires at least O(n) bits to store.

    0 讨论(0)
  • 2020-12-07 10:32

    I don't know how to do it in O(N), or even if it can be done in O(N). I know that it can be done in O(N log N) if you (use an appropriate) sort and compare.

    That being said, there are many O(N) techniques that can be done to show that one is NOT a permutation of the other.

    1. Check the length. If unequal, obviously not a permutation.
    2. Create an XOR fingerprint. If the value of all the elements XOR'ed together does not match, then it can not be a permutation. A match would however be inconclusive.
    3. Find the sum of all elements. Although the result may overflow, that should not be a worry when matching this 'fingerprint'. If however, you did a checksum that involved multiplying then overflow would be an issue.

    Hope this helps.

    0 讨论(0)
  • 2020-12-07 10:32

    The sum and the product will not guarantee the correct answer, since these hashes are subject to collisions, i.e. different inputs might potentially produce identical results. If you want a perfect hash, a single-number result that actually fully describes the numerical composition of the array, it might be the following.

    Imagine that for any number i in [1, N] range you can produce a unique prime number P(i) (for example, P(i) is the i-th prime number). Now all you need to do is calculate the product of all P(i) for all numbers in your array. The product will fully and unambiguously describe the composition of your array, disregarding the ordering of values in it. All you need to do is to precalculate the "perfect" value (for a permutation) and compare it with the result for a given input :)

    Of course, the algorithm like this does not immediately satisfy the posted requirements. But at the same time it is intuitively too generic: it allows you to detect a permutation of absolutely any numerical combination in an array. In your case you need to detect a permutation of a specific combination 1, 2, ..., N. Maybe this can somehow be used to simplify things... Probably not.

    0 讨论(0)
  • 2020-12-07 10:32

    it looks like asking to find duplicate in array with stack machine.

    it sounds impossible to know the full history of the stack , while you extract each number and have limited knowledge of the numbers that were taken out.

    0 讨论(0)
  • 2020-12-07 10:36

    Depending on how much space you have, relative to N, you might try using hashing and buckets.

    That is, iterate over the entire list, hash each element, and store it in a bucket. You'll need to find a way to reduce bucket collisions from the hashes, but that is a solved problem.

    If an element tries to go into a bucket with an item identical to it, it is a permutation.

    This type of solution would be O(N) as you touch each element only once.

    However, the problem with this is whether space M is larger than N or not. If M > N, this solution will be fine, but if M < N, then you will not be able to solve the problem with 100% accuracy.

    0 讨论(0)
  • 2020-12-07 10:38

    Here's proof it can't be done:

    Suppose by some artifice you have detected no duplicates in all but the last cell. Then the problem reduces to checking if that last cell contains a duplicate.

    If you have no structured representation of the problem state so far, then you are reduced to performing a linear search over the entire previous input, for EACH cell. It's easy to see how this leaves you with a quadratic-time algorithm.

    Now, suppose through some clever data structure that you actually know which number you expect to see last. Then certainly that knowledge takes at least enough bits to store the number you seek -- perhaps one memory cell? But there is a second-to-last number and a second-to-last sub-problem: then you must similarly represent a set of two possible numbers yet-to-be-seen. This certainly requires more storage than encoding only for one remaining number. By a progression of similar arguments, the size of the state must grow with the size of the problem, unless you're willing to accept a quadratic-time worst-case.

    This is the time-space trade-off. You can have quadratic time and constant space, or linear time and linear space. You cannot have linear time and constant space.

    0 讨论(0)
提交回复
热议问题