Hackerrank "Almost Equal" solution I've spent the best part of a day on this question. It is marked as Expert level. There are about fifteen submission test cases and my solution manages to satisfy the first four. However, from there on in it hits timeouts due to performance issues.

Hackerrank question

There doesn't seem to be much information or solutions for this question around, so I would appreciate if anyone had any suggestion on how I can improve the performance. Maybe I need to go back to the drawing board with my approach.


N = number of elements in the array
K = The height difference allowed
H = Array of heights
queries = 2D array of ranges within which you must find the number of matching pairs (i.e. how many fighters in this range meet the height requirements to fight each other)


My approach is to copy the subset (I know this is slow and would like to get around it somehow)and then run a quicksort over this new subset.

With this we can now quickly figure out what heights are within range of each other (i.e. if we get height = 1 and we know k = 2, then the maximum height he can fight against is going to be 3).

    static int[] solve(int n, int k, int[] h, int[][] queries) {
    // N = no. heights
    // K = Difference
    // L &amp; R = First and Last fighters
    int[] results = new int[queries.length];
    int count = 1;
    int pairs = 0;
    int l, r =0;

    for(int j=0; j&lt;queries.length; j++) {
        l = queries[j][0];
        r = queries[j][1];
        int[] range = Arrays.copyOfRange(h, l, r+1);

        int[] sortedSubset = sort(range);

        for(int i=0; i&lt;sortedSubset.length-1; i++) {
            count = i+1;
            while((count != sortedSubset.length) &amp;&amp; sortedSubset[count] &lt;= (sortedSubset[i]+k)) { 

                // While the current number is still in range of the number we are checking i.e. (number + k)
                pairs++;
                count++;
           }
        }
        results[j] = pairs;
        pairs = 0;
    }

    return results;
}



  A Sumo wrestling championship is scheduled to be held this winter
  in the HackerCity where N wrestlers
  from different parts of the world are going to participate.
  The rules state that two wrestlers can fight against each other
  if and only if the difference in their height
  is less than or equal to K, (i.e.)
  wrestler A and wrestler B can fight 
  if and only if |height(A)-height(B)|≤K.  
  
  Given an array H[], where 
  H[i] represents the height of the ith
  fighter, for a given l, r where 0 &lt;= l &lt;= r &lt; N, can you count the
  number of pairs of fighters between l and r (both inclusive) who
  qualify to play a game?
  
  Input Format
  The first line contains an integer N and K separated by
  a single space representing the number of Sumo wrestlers who are going
  to participate and the height difference K.
  The second line contains N integers separated by a single space, 
  representing their heights
  H[0] H[1] ... H[N - 1].
  The third line contains Q, the number of queries. 
  This is followed by Q lines each having two integers l and r
  separated by a space. 
  
  Output Format
  For each query Q, output the corresponding value of
  the number of pairs of fighters for whom the absolute difference of
  height is not greater that K. 
  
  Constraints
  1 &lt;= N &lt;= 100000
  0 &lt;= K &lt;= 109
  0 &lt;= H[i] &lt;= 109
  1 &lt;= Q &lt;= 100000
  0 &lt;= l &lt;= r &lt; N  
  
  Sample Input

5 2  
1 3 4 3 0  
3  
0 1  
1 3  
0 4  

  
  Sample Output

1  
3  
6  

  
  Explanation
  Query #0: Between 0 and 1 we have i,j as (0,1) and
  |H[0]-H[1]|=2 therefore output is 1.
  Query #1: The pairs (H[1],H[2]) (H[1],H[3])
  and (H[2],H[3]) are the pairs such that |H[i]-H[j]| &lt;=2.
  Hence output is 3.
  Query #2: Apart from those in Query #1, we have
  (H[0],H[1]), (H[0], H[3]), (H[0], H[4]), hence 6. 
  
  Timelimits  
  
  Timelimits are given here
Constraints
    1 &lt;= N &lt;= 100000
    0 &lt;= K &lt;= 109
    0 &lt;= H[i] &lt;= 109
    1 &lt;= Q &lt;= 100000
    0 &lt;= l &lt;= r &lt; N
  


My rule of thumb for this kind of challenge is that 109 operations is a limit. So, ignoring the hidden constant of Landau notation, we're looking at something which is \$O(N\sqrt N + Q\sqrt Q + Q\sqrt{N} + K)\$. In particular, each query shouldn't take more than \$\sqrt N\$ time. That would seem to push us towards a preprocessing step which is \$O(N\sqrt N + K)\$ and which allows us to process individual queries fast. Alternatively, we might have a preprocessing step which takes into account the queries, but that's likely to be more complicated.

Since your approach takes (in the worst case) \$O(QN\lg N)\$ time, it's definitely nowhere near complying with my rule of thumb.



If we consider first the idea of a preprocessing step which takes into account the queries, it's quite easy to construct a really nasty case where we have boundaries between every consecutive pair of wrestlers, and each one contributes to multiple queries. E.g. take the following 100000 queries:

(0, 99999), (1, 99998), (2, 99997), ..., (49999,50000),
(0, 49999), (1, 50000), (2, 50001), ..., (49999, 99998)


I don't find that approach promising.



Ideas which might be more promising are bucketing the wrestlers in buckets of width \$K\$, so that each wrestler can only interact with those in the same bucket and some of those in the adjacent buckets - although the "some of" is a problem; and inclusion-exclusion, although I can't quite get that to work. It's "fast enough" to precompute tables \$C[a]\$ which is the number of valid fights between \$i \le a &lt; j\$; \$L[a]\$ which is the number of valid fights between \$i &lt; j \le a\$; and \$R[a]\$ which is the number of valid fights between \$a \le i &lt; j\$. But the closest I can get to the number of valid fights between \$l \le i &lt; j \le r\$ is the difference of that with the number of valid fights between \$i \le l\$ and \$j \ge r\$.