字符串
前缀和
题目描述
给你一个顾客访问商店的日志,用一个下标从 0 开始且只包含字符 'N'
和 'Y'
的字符串 customers
表示:
如果第 i
个字符是 'Y'
,它表示第 i
小时有顾客到达。
如果第 i
个字符是 'N'
,它表示第 i
小时没有顾客到达。
如果商店在第 j
小时关门(0 <= j <= n
),代价按如下方式计算:
在开门期间,如果某一个小时没有顾客到达,代价增加 1
。
在关门期间,如果某一个小时有顾客到达,代价增加 1
。
请你返回在确保代价 最小 的前提下,商店的 最早 关门时间。
注意,商店在第 j
小时关门表示在第 j
小时以及之后商店处于关门状态。
示例 1:
输入: customers = "YYNY"
输出: 2
解释:
- 第 0 小时关门,总共 1+1+0+1 = 3 代价。
- 第 1 小时关门,总共 0+1+0+1 = 2 代价。
- 第 2 小时关门,总共 0+0+0+1 = 1 代价。
- 第 3 小时关门,总共 0+0+1+1 = 2 代价。
- 第 4 小时关门,总共 0+0+1+0 = 1 代价。
在第 2 或第 4 小时关门代价都最小。由于第 2 小时更早,所以最优关门时间是 2 。
示例 2:
输入: customers = "NNNNN"
输出: 0
解释: 最优关门时间是 0 ,因为自始至终没有顾客到达。
示例 3:
输入: customers = "YYYY"
输出: 4
解释: 最优关门时间是 4 ,因为每一小时均有顾客到达。
提示:
1 <= customers.length <= 105
customers
只包含字符 'Y'
和 'N'
。
解法
方法一:前缀和 + 枚举
我们先算出前 $i$ 小时有多少顾客到达,记录在前缀和数组 $s$ 中。
然后枚举商店关门的时间 $j$,计算代价,取代价最小且时间最早的关门时间即可。
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $customers$ 的长度。
Python3 Java C++ Go Rust
1
2
3
4
5
6
7
8
9
10
11
12 class Solution :
def bestClosingTime ( self , customers : str ) -> int :
n = len ( customers )
s = [ 0 ] * ( n + 1 )
for i , c in enumerate ( customers ):
s [ i + 1 ] = s [ i ] + int ( c == 'Y' )
ans , cost = 0 , inf
for j in range ( n + 1 ):
t = j - s [ j ] + s [ - 1 ] - s [ j ]
if cost > t :
ans , cost = j , t
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class Solution {
public int bestClosingTime ( String customers ) {
int n = customers . length ();
int [] s = new int [ n + 1 ] ;
for ( int i = 0 ; i < n ; ++ i ) {
s [ i + 1 ] = s [ i ] + ( customers . charAt ( i ) == 'Y' ? 1 : 0 );
}
int ans = 0 , cost = 1 << 30 ;
for ( int j = 0 ; j <= n ; ++ j ) {
int t = j - s [ j ] + s [ n ] - s [ j ] ;
if ( cost > t ) {
ans = j ;
cost = t ;
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 class Solution {
public :
int bestClosingTime ( string customers ) {
int n = customers . size ();
vector < int > s ( n + 1 );
for ( int i = 0 ; i < n ; ++ i ) {
s [ i + 1 ] = s [ i ] + ( customers [ i ] == 'Y' );
}
int ans = 0 , cost = 1 << 30 ;
for ( int j = 0 ; j <= n ; ++ j ) {
int t = j - s [ j ] + s [ n ] - s [ j ];
if ( cost > t ) {
ans = j ;
cost = t ;
}
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 func bestClosingTime ( customers string ) ( ans int ) {
n := len ( customers )
s := make ([] int , n + 1 )
for i , c := range customers {
s [ i + 1 ] = s [ i ]
if c == 'Y' {
s [ i + 1 ] ++
}
}
cost := 1 << 30
for j := 0 ; j <= n ; j ++ {
t := j - s [ j ] + s [ n ] - s [ j ]
if cost > t {
ans , cost = j , t
}
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 impl Solution {
#[allow(dead_code)]
pub fn best_closing_time ( customers : String ) -> i32 {
let n = customers . len ();
let mut penalty = i32 :: MAX ;
let mut ret = - 1 ;
let mut prefix_sum = vec! [ 0 ; n + 1 ];
// Initialize the vector
for ( i , c ) in customers . chars (). enumerate () {
prefix_sum [ i + 1 ] = prefix_sum [ i ] + ( if c == 'Y' { 1 } else { 0 });
}
// Calculate the answer
for i in 0 ..= n {
if penalty > (( prefix_sum [ n ] - prefix_sum [ i ]) as i32 ) + (( i - prefix_sum [ i ]) as i32 ) {
penalty = (( prefix_sum [ n ] - prefix_sum [ i ]) as i32 ) + (( i - prefix_sum [ i ]) as i32 );
ret = i as i32 ;
}
}
ret
}
}
GitHub