Find all triplets in array with sum less than or equal to given sum

后端 未结 5 2196
星月不相逢
星月不相逢 2020-12-15 10:57

This was recently asked to a friend in an interview and we do not know of any solution other than the simple O(n3) one.

Is there some better algorithm?

5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-15 11:36

    I'm keeping my original answer below, but this can actually be solved in O(n). My new solution uses a Queue to keep track of the triplets. It only returns the number of triplets but you could create a list to track the triplet lists pretty easily if that is what's required.

        class Queue (object):
          def __init__ (self):
            self.queue = []
            self.itemCount = 0
    
          def enqueue (self, item):
            self.queue.append (item)
            self.itemCount += 1
    
          def dequeue (self):
            self.itemCount += 1
            return (self.queue.pop(0))
    
    
        def findAllTriplets(li,S):
          if len(li) < 3:
            return "Not enough elements for triplets"
          tQ = Queue() # Queue to keep track of data
          tripletNum = 0 # Integer to track number of triplets to be returned
          tripletSum = 0 # Value of sum of consecutive list items for tripletNum evaluation
          for number in li:
            # Add the number to the queue immediately and add it to the current triplet sum
            tQ.enqueue(number)
            tripletSum += number
            # For the first 3 numbers only enqueue and add to the sum
            if tQ.itemCount < 3:
              continue
            # Afterwards, check if the sum of the latest three is less than S
            else:
              if(tripletSum <= S):
                tripletNum += 1
              # Dequeue the oldest element in the queue and subtract it from the tracked triplet sum
              tripletSum -= tQ.dequeue()
          return tripletNum
    

    I believe this algorithm should do the trick in O(N2). You should sort the array beforehand though.

    Essentially, I am just finding all possible triplets where the first index i is zero and the next index is j by searching through the remaining indices (k) for all sums less than or equal to x (or S in your case). After that, I increment j by 1 and repeat the process. Once j comes to the end of the array, I start the process over with my i being i + 1 now and keep going until i equals the second to last index value (since at that point there are no possible triplets left).

    Python code

    def numTriplets(a,x):
       if len(a) < 3:
           return None
       i = 0
       j = 1
       triplets = []
       while True:
          for k in range(j+1,len(a)):
             if a[i] + a[j] + a[k] <= x:
                triplets.append([i,j,k])
          j += 1
          if j == len(a) - 1:
             i += 1
             j = i + 1
          if i == len(a) - 2:
             return triplets
    

提交回复
热议问题