Problem#
You are given the customer visit log of a shop represented by a 0-indexed string customers
consisting only of characters 'N'
and 'Y'
:
if the ith
character is 'Y'
, it means that customers come at the ith
hour
whereas 'N'
indicates that no customers come at the ith
hour.
If the shop closes at the jth
hour (0 <= j <= n
), the penalty is calculated as follows:
For every hour when the shop is open and no customers come, the penalty increases by 1
.
For every hour when the shop is closed and customers come, the penalty increases by 1
.
Return theearliest hour at which the shop must be closed to incur a
minimum penalty.
Note that if a shop closes at the jth
hour, it means the shop is closed at the hour j
.
Examples#
Example 1#
1
2
3
4
5
6
7
8
9
Input: customers = "YYNY"
Output: 2
Explanation:
- Closing the shop at the 0 th hour incurs in 1 + 1 + 0 + 1 = 3 penalty.
- Closing the shop at the 1 st hour incurs in 0 + 1 + 0 + 1 = 2 penalty.
- Closing the shop at the 2 nd hour incurs in 0 + 0 + 0 + 1 = 1 penalty.
- Closing the shop at the 3 rd hour incurs in 0 + 0 + 1 + 1 = 2 penalty.
- Closing the shop at the 4 th hour incurs in 0 + 0 + 1 + 0 = 1 penalty.
Closing the shop at 2 nd or 4 th hour gives a minimum penalty. Since 2 is earlier, the optimal closing time is 2.
Example 2#
1
2
3
Input: customers = "NNNNN"
Output: 0
Explanation: It is best to close the shop at the 0 th hour as no customers arrive.
Example 3#
1
2
3
Input: customers = "YYYY"
Output: 4
Explanation: It is best to close the shop at the 4 th hour as customers arrive at each hour.
Constraints#
1 <= customers.length <= 10^5
customers
consists only of characters 'Y'
and 'N'
.
Solution#
Method 1 – Prefix Sum for Penalty Calculation#
Intuition#
For each possible closing hour, calculate penalty: open hours with ‘N’ and closed hours with ‘Y’. Use prefix sums for efficient calculation.
Approach#
Precompute prefix sums for ‘N’ and ‘Y’.
For each closing hour j (0 to n), penalty = count of ‘N’ in [0, j-1] + count of ‘Y’ in [j, n-1].
Track minimum penalty and earliest hour.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <string>
class Solution {
public :
int bestClosingTime(std:: string customers) {
int n = customers.size(), penalty = 0 , minPenalty = n+ 1 , res = 0 ;
for (char c : customers) if (c == 'Y' ) penalty++ ;
int curr = penalty;
for (int j = 0 ; j <= n; ++ j) {
if (curr < minPenalty) { minPenalty = curr; res = j; }
if (j < n) curr += (customers[j] == 'N' ) - (customers[j] == 'Y' );
}
return res;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func bestClosingTime (customers string ) int {
n , penalty := len(customers ), 0
for _ , c := range customers {
if c == 'Y' { penalty ++ }
}
minPenalty , res := penalty , 0
curr := penalty
for j := 0 ; j <= n ; j ++ {
if curr < minPenalty { minPenalty , res = curr , j }
if j < n {
if customers [j ] == 'N' { curr ++ } else if customers [j ] == 'Y' { curr -- }
}
}
return res
}
1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int bestClosingTime (String customers) {
int n = customers.length (), penalty = 0;
for (char c : customers.toCharArray ()) if (c == 'Y' ) penalty++ ;
int minPenalty = penalty+ 1, res = 0, curr = penalty;
for (int j = 0; j <= n; ++ j) {
if (curr < minPenalty) { minPenalty = curr; res = j; }
if (j < n) curr += (customers.charAt (j) == 'N' ? 1 : - 1);
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
fun bestClosingTime (customers: String): Int {
var penalty = customers.count { it == 'Y' }
var minPenalty = penalty+1
var res = 0
var curr = penalty
for (j in 0. .customers.length) {
if (curr < minPenalty) { minPenalty = curr; res = j }
if (j < customers.length) {
curr += if (customers[j] == 'N' ) 1 else -1
}
}
return res
}
}
1
2
3
4
5
6
7
8
9
10
class Solution :
def bestClosingTime (self, customers: str) -> int:
penalty = customers. count('Y' )
min_penalty, res, curr = penalty+ 1 , 0 , penalty
for j in range(len(customers)+ 1 ):
if curr < min_penalty:
min_penalty, res = curr, j
if j < len(customers):
curr += 1 if customers[j] == 'N' else - 1
return res
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
impl Solution {
pub fn best_closing_time (customers: String) -> i32 {
let n = customers.len();
let bytes = customers.as_bytes();
let mut penalty = bytes.iter().filter(|&& c| c== b 'Y' ).count() as i32 ;
let mut min_penalty = penalty+ 1 ;
let mut res = 0 ;
let mut curr = penalty;
for j in 0 ..= n {
if curr < min_penalty { min_penalty = curr; res = j as i32 ; }
if j < n {
curr += if bytes[j]== b 'N' { 1 } else { - 1 };
}
}
res
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
bestClosingTime (customers : string ): number {
let penalty = [...customers ].filter (c => c === 'Y' ).length ;
let minPenalty = penalty + 1 , res = 0 , curr = penalty ;
for (let j = 0 ; j <= customers .length ; ++ j ) {
if (curr < minPenalty ) { minPenalty = curr ; res = j ; }
if (j < customers .length ) {
curr += customers [j ] === 'N' ? 1 : - 1 ;
}
}
return res ;
}
}
Complexity#
⏰ Time complexity: O(n)
— Single pass.
🧺 Space complexity: O(1)
— Only variables.