0

Given an Array arr of size 100000, each element 0 <= arr[i] < 100. (not sorted, contains duplicates)

Find out how many triplets (i,j,k) are present such that arr[i] ^ arr[j] ^ arr[k] == 0 Note : ^ is the Xor operator. also 0 <= i <= j <= k <= 100000

I have a feeling i have to calculate the frequencies and do some calculation using the frequency, but i just can't seem to get started.

Any algorithm better than the obvious O(n^3) is welcome. :)

It's not homework. :)

7
  • Just curious.... if it's not homework, what is it? Commented Nov 18, 2010 at 11:13
  • Interview question, then? If not, can you explain what this will be used for - I can't think of an application for this right now? Commented Nov 18, 2010 at 11:13
  • It's Project Euler 310 :), managed to solve half the question...btw, the O(n^3) is running as we speak :) Commented Nov 18, 2010 at 11:14
  • 1
    There are only 100000 combinations of three values from 0 to 99 inclusive. Your array is 100000 long. Maybe coincidence, and even if not I'm not sure how it helps. Also, the condition is equivalent to arr[i] ^ arr[j] == arr[k]. Can't see how that helps either :) Commented Nov 18, 2010 at 11:16
  • @Paul, its actually, 74...not 100...i just meant to keep the numbers rounded. Commented Nov 18, 2010 at 11:17

6 Answers 6

4

I think the key is you don't need to identify the i,j,k, just count how many.

Initialise an array size 100

Loop though arr, counting how many of each value there are - O(n)

Loop through non-zero elements of the the small array, working out what triples meet the condition - assume the counts of the three numbers involved are A, B, C - the number of combinations in the original arr is (A+B+C)/!A!B!C! - 100**3 operations, but that's still O(1) assuming the 100 is a fixed value.

So, O(n).

Sign up to request clarification or add additional context in comments.

3 Comments

The problem is: i <= j <= k refer to indices not the integers themselves. As such this is erroneous I fear.
No, I don't think it is. And you seem to be commenting on some other issue as I don't rely on i <= j <= k.
Ah finally got it, by using combinatorial you ensure that you're not getting duplicates without having to rely on the order of indices, I was distracted by this condition and failed to see what it was meant to ensure.
1

Possible O(n^2) solution, if it works: Maintain variable count and two arrays, single[100] and pair[100]. Iterate the arr, and for each element of value n:

  • update count: count += pair[n]
  • update pair: iterate array single and for each element of index x and value s != 0 do pair[s^n] += single[x]
  • update single: single[n]++

In the end count holds the result.

Comments

1

Possible O(100 * n) = O(n) solution. it solve problem i <= j <= k. As you know A ^ B = 0 <=> A = B, so

long long calcTripletsCount( const vector<int>& sourceArray )
{
  long long res = 0;
  vector<int> count(128);
  vector<int> countPairs(128);
  for(int i = 0; i < sourceArray.size(); i++)
  {
    count[sourceArray[i]]++; // count[t] contain count of element t in (sourceArray[0]..sourceArray[i]) 
    for(int j = 0; j < count.size(); j++)
      countPairs[j ^ sourceArray[i]] += count[j]; // countPairs[t] contain count of pairs p1, p2 (p1 <= p2 for keeping order) where t = sourceArray[i] ^ sourceArray[j]
    res += countPairs[sourceArray[i]]; // a ^ b ^ c = 0 if a ^ b = c, we add count of pairs (p1, p2) where sourceArray[p1] ^ sourceArray[p2] = sourceArray[i]. it easy to see that we keep order(p1 <= p2 <= i)
  }  
  return res;
}

Sorry for my bad English...

5 Comments

Your nested loops make it O(n^2) I think.
count.size() = 128. It works with 100 000 elements less than 1 second.
oh, I solved Project Euler 310 problem using this algorithm:)
Your solution is more or less like mine, but the order of updating is different. I update count, then pair array, then single array. You update count array (mine single), then countPairs, then res (mine count). Our results will be different. IMHO mine order of updating is the correct one.
You can check it with brutforce algorithm at small tests. Assume that there is non-strict inequality. In your algorithm you calc triplets where i <= j < k
0

I have a (simple) O(n^2 log n) solution which takes into account the fact that i, j and k refer to indices, not integers.

A simple first pass allow us to build an array A of 100 values: values -> list of indices, we keep the list sorted for later use. O(n log n)

For each pair i,j such that i <= j, we compute X = arr[i]^arr[j]. We then perform a binary search in A[X] to locate the number of indices k such that k >= j. O(n^2 log n)

I could not find any way to leverage sorting / counting algorithm because they annihilate the index requirement.

Comments

0
Sort the array, keeping a map of new indices to originals. O(nlgn)
Loop over i,j:i<j. O(n^2)
  Calculate x = arr[i] ^ arr[j]
  Since x ^ arr[k] == 0, arr[k] = x, so binary search k>j for x. O(lgn)
  For all found k, print mapped i,j,k

O(n^2 lgn)

3 Comments

I think you need to restrict k to be greater than j, and so one need only search if x >= x[j].
if you sort the array, you lose the meaning of i, j and k in the original array. You may thus have a totally different count.
@Matthieu: Yes, you'll need to map i,j,k over. Edited.
0

Start with a frequency count of the number of occurrences of each number between 1 and 100, as Paul suggests. This produces an array freq[] of length 100.

Next, instead of looping over triples A,B,C from that array and testing the condition A^B^C=0, loop over pairs A,B with A < B. For each A,B, calculate C=A^B (so that now A^B^C=0), and verify that A < B < C < 100. (Any triple will occur in some order, so this doesn't miss triples. But see below). The running total will look like:

Sum+=freq[A]*freq[B]*freq[C]

The work is O(n) for the frequency count, plus about 5000 for the loop over A < B.

Since every triple of three different numbers A,B,C must occur in some order, this finds each such triple exactly once. Next you'll have to look for triples in which two numbers are equal. But if two numbers are equal and the xor of three of them is 0, the third number must be zero. So this amounts to a secondary linear search for B over the frequency count array, counting occurrences of (A=0, B=C < 100). (Be very careful with this case, and especially careful with the case B=0. The count is not just freq[B] ** 2 or freq[0] ** 3. There is a little combinatorics problem hiding there.)

Hope this helps!

4 Comments

That fills out the hand-waviy bit of my answer :) Thanks
You actually need to iterate over the array since i, j and k do not denote integers but index positions.
However, the calulation is on arr[i] etc, not i, so this doesn't matter. Given we don't need the values of i, j and k, and the array is undordered, this means any ordering of the values will give the same answer. In particular, the order that has the elements sorted is as valid as any other. This means the array of 100 counts contains the same information as the full "arr" array, for the purpooses of this question.
Notice the indices (A, B, C) of the frequency count array correspond not to the indices of the original array arr[i], but to the values stored within it. Splitting into cases based on whether A, B, C are distinct or not doesn't translate easily into conditions on i, j, k.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.