Sunday 11 July 2021

An algo for finding an arrangement of n integers such that for any two numbers a [i] and a [j] (i < j), their average does not lie between i and j

Given an array of n integers, how can we rearrange the numbers in it efficiently such that for any two numbers a[i] and a[j] (i < j), their average does not lie between i and jth index?
Please note that (i + 2) <= j < n where n is the length of the array. Only positive integers are allowed for numbers and averages, i.e. for 1 and 2, the average is 1.5 which we need to ignore. Numbers in the original array are distinct.

Let's take an example - if the given array is arr = [1, 2, 4, 7], this is not a valid arrangement at its current state as the average of arr[0] and arr[3] is 4 which the arr[2], so the average 4 is lying somewhere between 1 and 7. But [1, 2, 7, 4] is a valid arrangement.

I thought over this and this is the solution I could come up with, I couldn’t find a real scope for algorithm optimization. I have come across solutions like partitioning the array recursively based on even/odd index and merging them back but it didn't work for certain inputs.

from copy import copy
from collections import defaultdict

def arrange_numbers_no_avg_in_between(arr):

    def permutations_helper(i):
        if i == len(arr) - 1:
            num_index_mapping = defaultdict(list)
            for idx, num in enumerate(arr):
                num_index_mapping[float(num)].append(idx)
                
            for start in range(len(arr) - 2):
                for end in range(start + 2, len(arr)):
                    avg = (float(arr[start]) + float(arr[end])) / 2
                    if any(start < idx < end for idx in num_index_mapping[avg]):
                        return
            return copy(arr)
        else:
            for j in range(i, len(arr)):
                arr[i], arr[j] = arr[j], arr[i]
                result = permutations_helper(i + 1)
                if result:
                    return  result
                arr[i], arr[j] = arr[j], arr[i]
                
    return permutations_helper(0)


if __name__ == '__main__':
    print arrange_numbers_no_avg_in_between([1, 4, 2, 7])
    print arrange_numbers_no_avg_in_between([1, 201, 202, 431, 522])
    print arrange_numbers_no_avg_in_between(list(range(10)))

And here is the output I received,

[1, 2, 7, 4]
[1, 201, 202, 431, 522]
[0, 8, 4, 2, 6, 5, 1, 3, 9, 7]

The time complexity for my algorithm seems to be O(n.n!), I would appreciate any help for a better and efficient algorithm. Thanks.



from An algo for finding an arrangement of n integers such that for any two numbers a [i] and a [j] (i < j), their average does not lie between i and j

No comments:

Post a Comment