每段建筑物的平均高度

Submission

运行时间: 335 ms

内存: 86.5 MB

class Solution:
    def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]:
        diff = defaultdict(int)
        cnts = defaultdict(int)
        for a, b, h in buildings:
            diff[a] += h
            diff[b] -= h
            cnts[a] += 1
            cnts[b] -= 1
        cur, cnt, last, last_p, ans = 0, 0, None, None, []
        for k in sorted(diff.keys()):
            cur += diff[k]
            if last:
                if ans and ans[-1][1] == last_p and ans[-1][2] == last // cnt:
                    ans[-1][1] = k
                else:
                    ans.append([last_p, k, last // cnt])
            cnt += cnts[k]
            last, last_p = cur, k
        return ans

Explain

The solution uses a line sweep algorithm combined with differential counting. For each building, start and end positions are marked in a 'diff' dictionary where heights are added at the start and subtracted at the end. Another 'cnts' dictionary tracks how many buildings start or end at each point. By iterating over the sorted keys of these dictionaries, we compute the current total height and count of buildings at each position. This allows us to determine the average height for any segment where it remains constant. The result is appended to the list if the average height changes from the previous segment or a new segment starts.

时间复杂度: O(k log k)

空间复杂度: O(k)

class Solution:
    def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]:
        diff = defaultdict(int)  # Differential map to track height changes at each point
        cnts = defaultdict(int)  # Count map to track number of buildings starting or ending
        for a, b, h in buildings:
            diff[a] += h  # Add height at the start of a building
            diff[b] -= h  # Subtract height at the end of a building
            cnts[a] += 1  # Increment building count at start
            cnts[b] -= 1  # Decrement building count at end
        cur, cnt, last, last_p, ans = 0, 0, None, None, []
        for k in sorted(diff.keys()):
            cur += diff[k]  # Update current total height
            if last:
                if ans and ans[-1][1] == last_p and ans[-1][2] == last // cnt:
                    ans[-1][1] = k  # Extend the last segment if average height is the same
                else:
                    ans.append([last_p, k, last // cnt])  # Start a new segment
            cnt += cnts[k]  # Update the count of overlapping buildings
            last, last_p = cur, k  # Store the current height and position for next iteration
        return ans

Explore

通过为每个建筑的开始和结束位置在`diff`和`cnts`字典中分别增加和减少相应的高度和计数,可以确保没有遗漏或重复。每次循环添加建筑时,都会精确地修改这两个字典,因此只要输入的建筑数据是准确的,就能保证每个建筑的开始和结束都被正确地记录。此外,通过使用字典的键来唯一标识每个位置点,避免了重复处理同一位置的问题。

在实现中,如果`cnt`(即当前位置的建筑数量)为零,这意味着在该位置没有建筑物覆盖。在算法中,这种情况通常会跳过处理,因为没有建筑物覆盖的区间不需要计算平均高度。因此,这种区间不会在结果列表`ans`中表示。应当注意确保在两个有建筑物的有效区间之间的无覆盖区间不会被错误地计入结果。

当多个建筑物在同一位置重叠时,`diff`字典通过累加或累减每个建筑的高度变化来正确计算该点的总高度变化。同样,`cnts`字典通过对每个建筑在该点的开始和结束进行计数调整,确保正确地反映了重叠的建筑数量。因此,通过对每个建筑独立处理并更新这两个字典,算法可以准确地处理并记录重叠区域的总高度和建筑数量。

在算法的实现中,每次迭代结束时,都会检查是否需要将当前计算得到的区间添加到结果列表`ans`中。当迭代到最后一个位置时,如果存在未处理的有效区间(即`last`非空且`cnt`不为零),算法会进行一次最后的检查,确保这个区间被加入`ans`。这包括比较当前区间的平均高度是否与前一个区间不同,如果不同,则将其作为新区间添加到结果中。这样可以确保所有有效的区间都被正确记录,包括最后一个区间。