Alok
Alok

Reputation: 8978

Similarity Measure in Python

I am working on this coding challenge named Similarity Measure. Now the problem is my code works fine for some test cases, and failed due to the Time Limit Exceed problem. However, my code is not wrong, takes more than 25 sec for input of range 10^4.

I need to know what I can do to make it more efficient, I cannot think on any better solution than my code.

Question goes like this:

Problems states that given an array of positive integers, and now we have to answer based upon the Q queries.

Query: Given two indices L,R, determine the maximum absolute difference of index of two same elements lies between L and R

If in a range, there are no two same inputs then return 0

INPUT FORMAT

The first line contains N, no. of elements in the array A The Second line contains N space separated integers that are elements of the array A The third line contains Q the number of queries Each of the Q lines contains L, R

CONSTRAINTS

1 <= N, Q <= 10^4
1 <= Ai <= 10^4
1 <= L, R <= N

OUTPUT FORMAT

For each query, print the ans in a new line

Sample Input

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

Sample Output

0
0
2
2
3

Explanation

[2,3] - No two elements are same
[3,4] - No two elements are same
[2,4] - there are two 1's so ans = |4-2| = 2
[3,5] - there are two 2's so ans = |5-3| = 2
[1,5] - there are three 1's and two 2's so ans = max(|4-2|, |5-3|, |4-1|, |2-1|) = 3

Here is my algorithm:

  1. To take the input and test the range in a different method
  2. Input will be L, R and the Array
  3. For difference between L and R equal to 1, check if the next element is equal, return 1 else return 0
  4. For difference more than 1, loop through array
  5. Make a nested loop to check for the same element, if yes, store the difference into maxVal variable
  6. Return maxVal

My Code:

def ansArray(L, R, arr):
    maxVal = 0
    if abs(R - L) == 1:
        if arr[L-1] == arr[R-1]: return 1
        else: return 0
    else:
        for i in range(L-1, R):
          for j in range(i+1, R):
              if arr[i] == arr[j]:
                 if (j-i) > maxVal: maxVal = j-i
        return maxVal

if __name__ == '__main__':
    input()
    arr = (input().split())

    for i in range(int(input())):
        L, R = input().split()
        print(ansArray(int(L), int(R), arr))

Please help me with this. I really want to learn a different and a more efficient way to solve this problem. Need to pass all the TEST CASES. :)

Upvotes: 1

Views: 281

Answers (2)

lenik
lenik

Reputation: 23498

This can be solved as O(N) approximately the following way:

from collections import defaultdict

def ansArray(L, R, arr) :
    # collect the positions and save them into the dictionary
    positions = defaultdict(list)
    for i,j in enumerate(arr[L:R+1]) :
        positions[j].append(i)

    # create the list of the max differences in index
    max_diff = list()
    for vals in positions.values() :
        max_diff.append( max(vals) - min(vals) )

    # now return the max element from the list we have just created
    if len(max_diff) :
        return max(max_diff)
    else :
        return 0

Upvotes: 1

sanyassh
sanyassh

Reputation: 8500

You can try this code:

import collections


def ansArray(L, R, arr):
    dct = collections.defaultdict(list)
    for index in range(L - 1, R):
        dct[arr[index]].append(index)
    return max(lst[-1] - lst[0] for lst in dct.values())


if __name__ == '__main__':
    input()
    arr = (input().split())

    for i in range(int(input())):
        L, R = input().split()
        print(ansArray(int(L), int(R), arr))

Explanation:

dct is a dictionary that for every seen number keeps a list of indices. The list is sorted so lst[-1] - lst[0] will give maximum absolute difference for this number. Applying max to all this differences you get the answer. Code complexity is O(R - L).

Upvotes: 1

Related Questions