题目链接:
力扣https://leetcode-cn.com/problems/number-of-ways-to-select-buildings/
【前缀和】统计连续的0和1的个数,符合题意的方案无非就是010,101这两种,我们以中间的数字为基准来遍历统计的个数,以010为例:以1为基准,当前所在位置1的个数*前面0的个数*后面0的个数。
class Solution:
def numberOfWays(self, s: str) -> int:
n, t, ans = len(s), 0, 0
c = s[0]
cnt = []
for i in range(n):
if s[i] == c:
t += 1
else:
cnt.append(t)
t = 1
c = s[i]
cnt.append(t)
m = len(cnt)
if m < 3:
return 0
sum0, sum1 = 0, 0
for i in range(m):
if i % 2 == 0:
sum0 += cnt[i]
else:
sum1 += cnt[i]
i = 1
pre = cnt[0]
sum0 -= pre
while i + 1 < m:
ans += pre * cnt[i] * sum0
pre += cnt[i + 1]
sum0 -= cnt[i + 1]
i += 2
i = 2
pre = cnt[1]
sum1 -= pre
while i + 1 < m:
ans += pre * cnt[i] * sum1
pre += cnt[i + 1]
sum1 -= cnt[i + 1]
i += 2
return ans
【Java版】
class Solution {
public long numberOfWays(String s) {
List<Integer> cnt = new ArrayList<>();
int n = s.length(), i, t = 0;
long ans = 0;
char c, pre = s.charAt(0);
for(i = 0; i < n; i++){
c = s.charAt(i);
if(c == pre){
t++;
}else{
cnt.add(t);
t = 1;
pre = c;
}
}
cnt.add(t);
int sum0 = 0, sum1 = 0;
n = cnt.size();
if(n < 3) return 0;
for(i = 0; i < n; i++){
if(i % 2 == 0) sum0 += cnt.get(i);
else sum1 += cnt.get(i);
}
i = 1;
int p = cnt.get(0);
sum0 -= p;
while(i + 1 < n){
ans += (long)p * cnt.get(i) * sum0;
p += cnt.get(i + 1);
sum0 -= cnt.get(i + 1);
i += 2;
}
i = 2;
p = cnt.get(1);
sum1 -= p;
while(i + 1 < n){
ans += (long)p * cnt.get(i) * sum1;
p += cnt.get(i + 1);
sum1 -= cnt.get(i + 1);
i += 2;
}
return ans;
}
}