简体   繁体   中英

how can i write this algorithm more efficiently ? in a way that reduce time complexity?

So I write this code and I wanted to reduce time complexity of it but am not sure how, so what is the best way to write a more efficient algorithm so I can reduce time complexity, the code subtract from each element the first small number after it for example if the array is [1, 5, 6, 3, 2] then the result is [1, 2, 3, 1, 2] .

# an array with numbers
arr = [1, 5, 6, 3, 2]
# outer loop picks all element one by one
for i in range(0, len(arr), 1):
    Next = arr[i]
    # inner loop looks for the next smaller element
    for j in range(i + 1, len(arr), 1):
        if arr[i] > arr[j]:
            # if the condition is true, the element will be subtracted form the next smaller element
            # if there was no next smaller element, the element will kept without change
            Next = arr[i] - arr[j]
            break
    print(Next)

Indeed, your solution has O(n²) time complexity. You can improve on that.

Start from the end of the list and walk backwards.

While doing so, push an inspected list value on a stack when it is not less than the value currently on the top of the stack. At the same time output the difference.

When, on the other hand, an inspected value is less than the value on the top of the stack, then pop the stack until the value on the input value is no longer less than the value on top of the stack, and do again as described in the previous paragraph.

Here is an implementation of that idea:

def solve(arr):
    stack = [0]
    result = arr[:]
    # outer loop picks all element one by one
    for i in range(len(arr) - 1, -1, -1):
        val = arr[i]
        while val <= stack[-1]:
            stack.pop()
        result[i] = val - stack[-1]
        stack.append(val)
    return result

Call this function as follows:

arr = [1, 5, 6, 3, 2]
print (solve(arr))   # [1, 2, 3, 1, 2]

This algorithm has a linear time time complexity: O(n) . Although the inner while loop looks suspicious of a non-linear time complexity, it still is, because a given list value will at most be pushed and pulled only once on/off the stack.

Use a stack where each item on the stack is a tuple: (index, value) . Pop items off the stack when a smaller value is found. Then push the new tuple onto the stack. In pseudocode:

for each array element
   while the stack is not empty
      if the top stack_value is greater than the element_value
         pop the (index, stack_value) from the stack
         set arr[index] = stack_value - element_value
   push the tuple (index, element_value) onto the stack

And in python:

arr = [1, 5, 6, 3, 2]
stack = []
for i in range(len(arr)):
   while len(stack) and stack[-1][1] > arr[i]:
      index, value = stack.pop()
      arr[index] = value - arr[i]
   stack.append((i, arr[i]))
print arr    # [1, 2, 3, 1, 2]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM