This is a programming problem activity from my university. I am going to modify the problem to avoid plagiarism.
Let's say you have n people in a group. For each person, we number them from 0 to n−1. Each person has a personality value exhibited in a list. For example, a list [2, 3, 4, 6] exhibits that person 0 has a personality value of 2, person 1 has a personality value of 3, person 2 has a personality value of 3, and person 3 has a personality value of 6.
We define the enjoyment one person has with another person as |pi - pj| where i and j are subscripts of p and are indices of the list.
To better illustrate let us use the list again as the example.
- The enjoyment person 0 feels with person 1 is |2 - 3| which is 1.
- The enjoyment person 0 feels with person 2 is |2 - 4| is 2,
- The enjoyment person 0 feels with person 3 is |2 - 6| which is 4 and this continues for person 1 and so on.
I want to create a function that returns the third largest enjoyment that a person feels toward another person in the group. So for the list above, I should get an output of [1, 1, 1, 2]. It is guaranteed that a group of friends is greater than 4. The personality can also be negative.
Code:
def third_enjoyment(p: list[int]) -> list[int]:
n: int = len(p)
e: list[int] = []
for i in range(n):
enjoyment = [abs(p[i] - p[j]) for j in range(n) if j != i]
enjoyment.sort()
third_enjoyment = enjoyment[-3]
e.append(third_enjoyment)
return e
Here is my solution for this problem. I am not sure about the time but I think this solution has a time complexity of O(n^2) (not too sure as we haven't discussed how time complexities works) which is bad as when I try to submit my code to the judge it exceeds the time limit. I want to know a better way to solve this problem that would be faster than this brute force solution.
I think one way you can optimize the algorithm is to sort the personality value list while keeping its original indices by storing the each item in the list in the tuple structure of
(<p value>, <original index>)For each item with index
iin the sorted list, you know that largest difference with its value is either in the left side or the right side of that item in the sorted list. You can use two pointersl,rrepresenting the index of the left and right side of the item in the sorted list respectively and compare its difference with the item's value (abs(value - sp[l][0]) >= abs(sp[i][0] - sp[r][0])). Initially,landrare initialized with0andn-1respectively, represent the far left and far right end of the itemiin the sorted list. If left side has larger difference than the right side, you know the left side has the largest difference so you increaselindex by 1, closer to the item's index, to find the second largest difference. If right side has larger difference than the left side, you know the right side has the largest difference so you decreaserindex by 1, closer to the to find the second largest difference. You can keep doing this 3 times to get the third largest difference and apply the result to the array at the given original index. One thing to note, is thatlboundary can only be[0, i - 1]andrboundary can only be[i + 1, n - 1]so that iflorrhit their boundary first, only the other pointer has the right result and can be continuously increase/decrease until it reaches 3 total iterationThe total time complexity would be
O(nlog(n) + n)which is more efficient thanO(n^2)