Skip to content

Commit e417108

Browse files
Add 'Number of Visible People in a Queue'
1 parent 264c292 commit e417108

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ A collection of LeetCode solutions
7676

7777
[Next Permutation](./src/next_permutation.py)
7878

79+
[Number of Visible People in a Queue](./src/number_of_visible_people_in_a_queue.py)
80+
7981
[Palindromic Substrings](./src/palindromic_substrings.py)
8082

8183
[Permutation in String](./src/permutation_in_string.py)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
1944. Number of Visible People in a Queue
3+
4+
https://leetcode.com/problems/number-of-visible-people-in-a-queue
5+
6+
NOTES
7+
* Traverse the array from the right and use a monotonically decreasing stack.
8+
9+
A brute force solution would be to iterate from 0 to n-1 and with each
10+
iteration, count the number of people for which heights[i] > heights[j]. This
11+
solution would require O(n^2) time complexity.
12+
13+
The optimal solution leverages a monotonically decreasing stack, which
14+
maintains the indices of the heights of people, which can be seen.
15+
16+
The solution can be optimized by combining the steps for determining the number
17+
of people the ith person can see to their right in the queue and maintaining
18+
the monotonic property.
19+
"""
20+
21+
from collections import deque
22+
23+
24+
class Solution:
25+
def canSeePersonsCount(self, heights: list[int]) -> list[int]:
26+
n = len(heights)
27+
stack: deque[int] = deque()
28+
ans: list[int] = [0] * n
29+
30+
for i in reversed(range(n)):
31+
# Determine the number of people the ith person can see to their
32+
# right in the queue.
33+
#
34+
# The ith person can see the jth person if i < j and
35+
# min(heights[i], heights[j]) > max(heights[i+1...j-1]).
36+
if stack:
37+
min_height = min(heights[i], heights[stack[0]])
38+
j = len(stack) - 1
39+
while j >= 0 and min_height > heights[stack[j]]:
40+
j -= 1
41+
ans[i] = len(stack) - j
42+
43+
# Maintain monotonic property.
44+
while stack and heights[i] > heights[stack[-1]]:
45+
stack.pop()
46+
47+
stack.append(i)
48+
49+
return ans
50+
51+
52+
class OptimizedSolution:
53+
def canSeePersonsCount(self, heights: list[int]) -> list[int]:
54+
n = len(heights)
55+
stack: deque[int] = deque()
56+
ans: list[int] = [0] * n
57+
58+
for i in reversed(range(n)):
59+
# Determine the number of people the ith person can see to their
60+
# right in the queue, while maintaining the monotonic property.
61+
while stack and heights[i] > heights[stack[-1]]:
62+
stack.pop()
63+
ans[i] += 1
64+
if stack:
65+
ans[i] += 1
66+
67+
stack.append(i)
68+
69+
return ans
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
1944. Number of Visible People in a Queue
3+
4+
https://leetcode.com/problems/number-of-visible-people-in-a-queue
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.number_of_visible_people_in_a_queue import OptimizedSolution, Solution
10+
11+
12+
class TestSolution(TestCase):
13+
def test_1(self):
14+
exp = [3, 1, 2, 1, 1, 0]
15+
assert Solution().canSeePersonsCount([10, 6, 8, 5, 11, 9]) == exp
16+
17+
def test_2(self):
18+
exp = [4, 1, 1, 1, 0]
19+
assert Solution().canSeePersonsCount([5, 1, 2, 3, 10]) == exp
20+
21+
22+
class TestOptimizedSolution(TestCase):
23+
def test_1(self):
24+
exp = [3, 1, 2, 1, 1, 0]
25+
assert OptimizedSolution().canSeePersonsCount([10, 6, 8, 5, 11, 9]) == exp
26+
27+
def test_2(self):
28+
exp = [4, 1, 1, 1, 0]
29+
assert OptimizedSolution().canSeePersonsCount([5, 1, 2, 3, 10]) == exp

0 commit comments

Comments
 (0)