2
for _ in range(int(input())):
    num=int(input())
    a=list(map(int,input().split()))[:num]
    sum=0
    for i in range(len(a)):
        j=a[i]
        count=0
        key=0
        for k in range(len(a)):
            if j==a[k]:
                key=k
        sum+=abs(key-i)
    print(sum)

Given an integer array. The task is to calculate the sum of absolute difference of indices of first and last occurrence for every integer that is present in the array.

Required to calculate the sum of the answer for every such that occurs in the array.

One input:

1 2 3 3 2

Sample Output:

4

Explanation: The elements which occur in the array are 1,2,3.

  1. it has only occurred once so the answer for 1 is 0.
  2. it has two occurrences at 2 and 5 so |5-2|=3
  3. it has two occurrences at 3 and 4 so |4-3|=1.

So total sum=0+3+1=4. p.s: The first loop is for test cases.

Pleae suggest me to reduce time-complexity.

2
  • What's the question? Commented Dec 22, 2020 at 10:31
  • Check again sir, I hope it is clear now Commented Dec 22, 2020 at 10:33

4 Answers 4

1

intially you can create a dictiory of unique number and append all the index of each number and then in second loop you can get the diffrence of each integar.

for _ in range(int(input())):
    num=int(input())
    a=list(map(int,input().split()))[:num]
    sum=0
    nums = {}
    for i in range(len(a)):
        j=a[i]
        if j not in nums:
            nums[j] = []
        
        nums[j].append(i)
    
    for key in nums:
        sum += abs(nums[key][-1] - nums[key][0])
    print(sum)
Sign up to request clarification or add additional context in comments.

Comments

1

This answer uses the same reasoning as others: that is storing the indices as a list of values in a dictionary, but uses a few built-in functions and methods to reduce code and make it 'cleaner'.

In [11]: array = [1, 2, 3, 3, 2]

In [12]: indices = {}

In [13]: for ix, num in enumerate(array, start=1):
    ...:     indices.setdefault(num, []).append(ix)
    ...:

In [14]: total = 0

In [15]: for num, ixes in indices.items():
    ...:     if len(ixes) == 1:
    ...:         continue
    ...:     else:
    ...:         total += abs(ixes[-1] - ixes[0])
    ...:

In [16]: total
Out[16]: 4

enumerate is a function that creates a sequence of tuple pairs from a given sequence like a list. The first element is an "index" (by default, set to 0, but you can start from any integer) and the second is the actual value from the original sequence.

setdefault is a method on a dictionary that returns the value for a given key, but if that key doesn't exist, inserts the key and sets as its default value the item passed in as the second parameter; in this case, it's an empty list to store the indices.

items is again a method on dictionaries with which one can loop through one key-value pair at a time.

Comments

1

Sounds like hackerrank. As usual, most of the provided information of the problem is irrelevant and can be forgotten as soon as seen.

You need:

  • the index when an element occures first: you add it as negative to the total and put it into the dictionary
  • if the value is already in the dict, update the position only
  • at the end you sum all values of the dict and add it to your summation

Code:

num = 5
a = list(map(int,"1 2 3 3 2".split()))
s = 0
d = {}
for idx, num in enumerate(a):
  if num not in d:
      s -= idx
  d[num] = idx
  
print(s+sum(d.values()))

Output:

4

This uses a dictionary and strictly 2 loops - one over the n given numbers and one over u distinct numbers inside it if you ignore the int-conversion step wich already loops once over all of them.

Space:

  • the total sum and 1 index for each unique number which makes it worstcase O(n+1) in space (each number is also unique)

Time:

  • normally you get O(n + u) wich is less then the worst case (all numbers are unique) which would be O(2*n). 2 is only a factor - so it is essentially O(n) in time.

If you still have time-problems, using a collections.defaultdict(int) should be faster.

Comments

1

Solution 1 (dict): One way to it is by using a dictionary for each item, saving all indices and get the difference of last and first occurence for each item. See below:

def get_sum(a):
    d={i:[] for i in set(a)}
    for i in range(len(a)):
        d[a[i]].append(i)
    sum=0
    for i in d.values():
        sum+=i[-1]-i[0]
    return sum
   

Solution 2 (reversed list): Another way is to use the reversed list and use list.index(item) for both original and reverse list and get the difference. See below:

def get_sum2(a):
   m=a[::-1]
   return sum(len(m)-m.index(i)-1-a.index(i) for i in set(a))

Output:

>>>get_sum([1,2,3,3,2])

4

>>>get_sum2([1,2,3,3,2])

4

5 Comments

answer still has 3 for loops technically
Thanks I added another solution, much faster
@NitinGoyal the number of loops is irrelevant
@IoaTzimas sum(len(m)-m.index(i)-1-a.index(i) for i in set(a)) kills your complexity. making it quadratic in the worst case
What do you mean? Its just a sum of for items, i don't think it's too complex for python. Actually it's 2 items that change each time, as len and 1 are constant

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.