LeetCode-Problems / 2256. Minimum Average Difference / 2256. Minimum Average Difference.py
2256. Minimum Average Difference.py
Raw
# 12-3-2022 2256. Minimum Average Difference
# https://leetcode.com/problems/minimum-average-difference/

# Ooh, whats that Data Structure that does this? Its a tree Structure
# that also keeps information like a running sum? Fenwick Tree!
# Actually LESS effecient than just summing it ourselves once here
# as we are given a fixed arrany and do not need the ability to update it
# dynamically. O(log n) to get sum where we can just do it O(n) to start
# (both) have this requirement, then just O(1) for lookup

# Still, shall we give it a go for practice? It is a
# slightly more complicated DS and I've seen it come up before


class ftree:
    # Constructs and returns a Binary Indexed Tree for given
    # array of size n.
    def __init__(self, arr, n):
        # Create and initialize BITree[] as 0
        self.BITTree = [0] * (n + 1)
        # Store the actual values in BITree[] using update()
        for i in range(n):
            self.updatebit(n, i, arr[i])
        # return BITTree

    def getsum(self, i):
        s = 0  # initialize result
        # index in BITree[] is 1 more than the index in arr[]
        i = i + 1
        # Traverse ancestors of BITree[index]
        while i > 0:
            # Add current element of BITree to sum
            s += self.BITTree[i]
            # Move index to parent node in getSum View
            i -= i & (-i)
        return s

    # Updates a node in Binary Index Tree (BITree) at given index
    # in BITree. The given value 'val' is added to BITree[i] and
    # all of its ancestors in tree.
    def updatebit(self, n, i, v):
        # index in BITree[] is 1 more than the index in arr[]
        i += 1
        # Traverse all ancestors and add 'val'
        while i <= n:
            # Add 'val' to current node of BI Tree
            self.BITTree[i] += v
            # Update index to that of parent in update View
            i += i & (-i)


class Solution:
    def minimumAverageDifference(self, nums: List[int]) -> int:
        nums_ftree = ftree(nums, len(nums))

        max_sum = nums_ftree.getsum(len(nums) - 1)
        min_avg = max_sum
        mindex = 0

        for i in range(len(nums)):
            i_sum = nums_ftree.getsum(i)
            new_avg = abs(
                (i_sum // (i + 1)) - ((max_sum - i_sum) // max((len(nums) - i - 1), 1))
            )
            if new_avg < min_avg:
                min_avg = new_avg
                mindex = i
        return mindex


# class Solution:
#     def minimumAverageDifference(self, nums: List[int]) -> int:
#         def getsum(BITTree,i):
#             s = 0 #initialize result
#             # index in BITree[] is 1 more than the index in arr[]
#             i = i+1
#             # Traverse ancestors of BITree[index]
#             while i > 0:
#                 # Add current element of BITree to sum
#                 s += BITTree[i]
#                 # Move index to parent node in getSum View
#                 i -= i & (-i)
#             return s

#         # Updates a node in Binary Index Tree (BITree) at given index
#         # in BITree. The given value 'val' is added to BITree[i] and
#         # all of its ancestors in tree.
#         def updatebit(BITTree , n , i ,v):
#             # index in BITree[] is 1 more than the index in arr[]
#             i += 1
#             # Traverse all ancestors and add 'val'
#             while i <= n:
#                 # Add 'val' to current node of BI Tree
#                 BITTree[i] += v
#                 # Update index to that of parent in update View
#                 i += i & (-i)

#         # Constructs and returns a Binary Indexed Tree for given
#         # array of size n.
#         def construct(arr, n):
#             # Create and initialize BITree[] as 0
#             BITTree = [0]*(n+1)
#             # Store the actual values in BITree[] using update()
#             for i in range(n):
#                 updatebit(BITTree, n, i, arr[i])
#             return BITTree

#         ftree = construct(nums, len(nums))

#         max_sum = getsum(ftree, len(nums)-1)
#         min_avg = max_sum
#         mindex = 0

#         for i in range(len(nums)):
#             i_sum = getsum(ftree, i)
#             # left = (i_sum//(i+1))
#             # right = (max_sum - i_sum)//(len(nums)-i-1)
#             # new_i_avg = abs(    (i_sum//(i+1)) - (  (max_sum - i_sum)//(len(nums)-i-1)  )    )
#             new_avg = abs(    (i_sum//(i+1)) - (  (max_sum - i_sum)//max((len(nums)-i-1),1)  )    )
#             if new_avg < min_avg:
#                 min_avg = new_avg
#                 mindex = i
#         return mindex