You are given a 0-indexed 2D integer array peaks where peaks[i] = [xi, yi] represents the coordinates of the ith mountain peak in a mountain range.
A mountain is visible if its peak is not hidden behind any other peak. In other words, the ith mountain is not visible if there exists an integer j such that 0 <= j < peaks.length and i != j, where both xj >= xi and yj >= yi are satisfied.
Return the number of visible mountains.
Example 1:
Input: peaks = [[0,1],[1,3],[3,7],[5,5],[4,2]] Output: 3 Explanation: - Mountain at index 0 is visible because no other mountain has a peak to its right and higher. - Mountain at index 1 is not visible because the mountain at index 2 has a peak to its right and higher. - Mountain at index 2 is visible because no other mountain has a peak to its right and higher. - Mountain at index 3 is visible because no other mountain has a peak to its right and higher. - Mountain at index 4 is not visible because the mountain at index 3 has a peak to its right and higher. There are 3 visible mountains so we return 3.
Example 2:
Input: peaks = [[1,0],[2,2],[0,1]] Output: 2 Explanation: - Mountain at index 0 is visible because no other mountain has a peak to its right and higher. - Mountain at index 1 is visible because no other mountain has a peak to its right and higher. - Mountain at index 2 is not visible because the mountain at index 1 has a peak to its right and higher. There are 2 visible mountains so we return 2.
Constraints:
1 <= peaks.length <= 1050 <= xi, yi <= 105When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to counting visible mountains means we're going to check every single mountain against every other mountain. We are going to directly simulate what it means for one mountain to block another from view. This will be very thorough, but probably slow for a large number of mountains.
Here's how the algorithm would work step-by-step:
def find_number_of_visible_mountains_brute_force(mountain_positions, mountain_heights):
number_of_mountains = len(mountain_positions)
is_mountain_visible = [True] * number_of_mountains
# Assume all mountains are visible initially
for current_mountain_index in range(number_of_mountains):
for other_mountain_index in range(number_of_mountains):
# Skip comparison with itself
if current_mountain_index == other_mountain_index:
continue
# Check if the other mountain is in front
if mountain_positions[other_mountain_index] > mountain_positions[current_mountain_index]:
# Check if the other mountain is taller if mountain_heights[other_mountain_index] >= mountain_heights[current_mountain_index]:
# If taller, it blocks current mountain is_mountain_visible[current_mountain_index] = False
break
visible_mountain_count = 0
for visible in is_mountain_visible:
if visible:
visible_mountain_count += 1
return visible_mountain_countThe problem can be efficiently solved by focusing on identifying duplicate mountains and the mountains completely hidden behind others. We can determine visible mountains by strategically comparing their positions and sizes.
Here's how the algorithm would work step-by-step:
def finding_the_number_visible_mountains(mountains):
mountain_positions = set()
duplicate_count = 0
# Count duplicates, treating same positions as one mountain
for position, height in mountains:
if (position, height) in mountain_positions:
duplicate_count += 1
mountain_positions.add((position, height))
unique_mountains = []
mountain_positions = set()
for position, height in mountains:
if (position, height) not in mountain_positions:
unique_mountains.append((position, height))
mountain_positions.add((position, height))
# Sort mountains by position, then by height
sorted_mountains = sorted(unique_mountains, key=lambda x: (x[0], -x[1]))
visible_mountains_count = 0
leftmost_reach = float('-inf')
rightmost_reach = float('-inf')
for position, height in sorted_mountains:
left_edge = position - height
right_edge = position + height
# A mountain is visible if it is not hidden
if left_edge > leftmost_reach and right_edge > rightmost_reach:
visible_mountains_count += 1
# Update the furthest reaches
leftmost_reach = max(leftmost_reach, right_edge)
rightmost_reach = max(rightmost_reach, right_edge)
return visible_mountains_count| Case | How to Handle |
|---|---|
| Empty input list of mountains. | Return 0 as there are no mountains to be visible. |
| All mountains have the exact same height and location. | Return 1, as only one is visible, and others are hidden. |
| Mountains are sorted by peak location. | Algorithm should correctly process regardless of input order; no specific handling needed. |
| Integer overflow when calculating the shadow range of a mountain. | Use a wider data type (e.g., long) or alternative representation for range calculations to prevent overflow. |
| Maximum number of mountains allowed based on memory constraints. | Ensure the algorithm's space complexity remains reasonable and within memory limits by using appropriate data structures. |
| Mountains are densely packed, with almost fully overlapping shadows. | Algorithm efficiently accounts for overlaps to only count truly visible mountains. |
| Floating point precision issues when comparing peak locations or heights. | Use a tolerance value when comparing floats to account for potential precision errors. |
| Negative peak locations and/or heights. | Algorithm should support negative coordinates and heights, defining visibility accordingly. |