6

You have an array with n=2k+2 elements where 2 elements haven't pair. Example for 8 elemets array: 1 2 3 47 3 1 2 0. "47" and "0" haven't pair in array. If I have array where only 1 element has't pair, I solve this problem with XOR. But I have 2 unpair elements! What can I do? Solution could be for a O(n) time performance and for O(1) additional memory.

rodart
  • 77
  • 4

4 Answers4

8

Some hints...

It will take 2 passes. First, go through the list and XOR all elements together. See what you get. Proceed from there.

Edit: The key observation about the result of the first pass should be that it shows you the set of bits in which the 2 unpaired elements differ.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Ok, I have xor-result this two unpair elements. And what next i don't know – rodart Feb 02 '12 at 16:08
  • 1
    This looks like a homework/puzzle problem so I'm trying to avoid just giving you the answer. Play with it a little bit. I'm pretty sure this exact question has been asked before too, so you could instead opt to search... – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:12
  • @user1185443, you should read about a `xor` operation a bit more. There is another application of `xor` to change two elements without using additional space. `a, b -> a = a xor b, b = a xor b, a = a xor b`. This may help. – Alex Nikolaenkov Feb 02 '12 at 16:17
  • This problem from interview. And I have been thinking for 2 days! I really have no chance to come up with an answer – rodart Feb 02 '12 at 16:21
  • 6
    Found the actual implementation at http://www.geeksforgeeks.org/archives/2457 Credit goes to @R.. – The Real Baumann Feb 02 '12 at 16:34
  • After first pass i have res = a xor b, where "a" and "b" are unpair elements. Thereafter i pass my array in second time and by the end i have 0 in res. In what sense? – rodart Feb 02 '12 at 16:35
1

Use INT_MAX/8 bytes of memory. Walk the array. XOR the bit corresponding to each value with 1. If there are 0 or 2 instances the bit will end up 0. If there is only one instance, it will be set. O(1) mem, O(N) time.

AShelly
  • 34,686
  • 15
  • 91
  • 152
  • 1
    That's not O(1) because you invoked `INT_MAX`. It's O(N). – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:06
  • `O(N)` memory; you can have `N/2 + 2` distinct elements and need a bit for each of them. – Michael J. Barber Feb 02 '12 at 16:07
  • And...good luck fitting that bit array on earth if by chance `int` happens to be 64-bit... ;-) – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:11
  • @real, this will result in an array with a bit set for any element which appears an odd number of times. Identifying which bits are set is constant time, since the array is constant size. Yes, both constants are big, but they are constant. – AShelly Feb 02 '12 at 16:15
  • 1
    @R, it is constant for any given platform/ implementation. It just happens to be a very large constant. – AShelly Feb 02 '12 at 16:15
  • @AShelly: By your argument all algorithms are O(1) in space and time. The space of RSA keys that fit in 4gb of memory is a finite space, so cracking RSA is O(1) too, just with a big constant? – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:23
  • @R..: I'm not going to talk about the algorithm per se, but AShelly is right. An amount of memory required for the proposed algorithm does not grow with the growth of an array size, hence O(1). Imagine an array of bytes. We need only 256 bits of memory even if we have 10^1000 elements... or just 257. – Igor Korkhov Feb 02 '12 at 16:38
  • It does grow with the array size, and per my comment above, the algorithm is completely non-viable when `int` is 64-bit. – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:45
  • @R..: it is non-viable, agreed, and I did read your comment. But since INT_MAX == const and doesn't depend on N, the space complexity is O(1). Michael J. Barber's point is incorrect as well. If an element can have only M possible values (- INT_MIN <= M <= INT_MAX in this case) then we can't have more than M **distinct** elements. – Igor Korkhov Feb 02 '12 at 17:03
  • `INT_MAX` depends on the size/max value of your input. If the input is larger, you must either use a machine with larger ints or use a bignum implementation. – R.. GitHub STOP HELPING ICE Feb 02 '12 at 17:05
  • @R..: Yes, it does, but it has nothing to do with the *length* of an auxiliary array required. You need exactly `2^ / 8` bytes, which is *constant*. I'm not saying that the algorithm is viable for 64-bit integers, I'm just saying that it does require O(1) mem. – Igor Korkhov Feb 02 '12 at 17:20
  • Size of element is not constant for the general problem. Numbers can be arbitrarily large. You could consider them growing separately, in which case it would be O(2^M) where M is the size of the entries. – R.. GitHub STOP HELPING ICE Feb 02 '12 at 17:46
  • @R..: if elements themselves can grow in size, then your XOR solution is O(N*M) (N iterations to scan the whole array, M iterations to XOR two elements). All in all, my only point is: for any *fixed* element size the algorithm proposed by AShelly requires O(N) time and O(1) memory, where N is the length of input. Is this OK? – Igor Korkhov Feb 02 '12 at 18:01
  • You do realize that if the input values are bounded, the size of the input array is also bounded, right? (Since each element can only occur once or twice.) Thus there's no taking N to infinity unless the magnitude of individual elements can also grow. – R.. GitHub STOP HELPING ICE Feb 03 '12 at 00:32
1
  1. Scan the Array and put each number and count in hash.
  2. Rescan and find out the items with count=1.

This is O(n).

  • 2
    And how much memory is needed? – asaelr Feb 03 '12 at 00:03
  • While this is definitely the solution that I would use in production code, the space requirement in the OP was `O(1)`, which is not met by this approach. The question seems to be designed towards a bit twiddling solution (see Shivam Singh's answer: http://stackoverflow.com/a/43609845/2445184). – cmaster - reinstate monica Apr 25 '17 at 13:12
0

You can try this.It will take O(n) time

        int xor = arr[0];
        int set_bit_no;
        int i;
        int x = 0; //First unpair number
        int y = 0; //second unpair number
        for (i = 1; i < n; i++)
            xor ^= arr[i];

        set_bit_no = xor & ~(xor-1);//Get the rightmost set bit in set_bit_no
        for (i = 0; i < n; i++)
        {
            if (arr[i] & set_bit_no) {
                //XOR of first set 
                x = x ^ arr[i];
            }
            else
            {
                //XOR of second set
                y = y ^ arr[i];
            }
        }

Explanation... arr[] = {2, 4, 7, 9, 2, 4} 1) Get the XOR of all the elements. xor = 2^4^7^9^2^4 = 14 (1110) 2) Get a number which has only one set bit of the xor.
Since we can easily get the rightmost set bit, let us use it. set_bit_no = xor & ~(xor-1) = (1110) & ~(1101) = 0010 Now set_bit_no will have only set as rightmost set bit of xor. 3) Now divide the elements in two sets and do xor of
elements in each set, and we get the non-repeating elements 7 and 9.

  • 1
    Whilst this code snippet is welcome, and may provide some help, it would be [greatly improved if it included an explanation](//meta.stackexchange.com/q/114762) of *how* it addresses the question. Without that, your answer has much less educational value - remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Apr 25 '17 at 12:08
  • can't understand – Shridutt Kothari Aug 02 '19 at 14:16