解题思路: (就是找101 ,010的个数)
1.暴力求解
以每一个数为中心,如果是 1 ,往左边找0,往右边找0, ans += left * right , (left,right都为0的个数) ; 如果是 0 ,往左边找1,往右边找1 , ans += left * right ( left,right都为1的个数 ). 时间复杂度 O(N^2). (超时)
代码:
class Solution {
public:
long long numberOfWays(string s)
{
int sz = s.size();
long long ans = 0;
for(int i = 1 ;i < sz-1 ;++i)
{
int leftCount = 0;
int rightCount = 0;
if(s[i] == '0')
{
int j = 0;
for(; j < i ; ++j)
{
if(s[j] == '1')
leftCount++;
}
++j;
for( ; j < sz ; ++j)
{
if(s[j] == '1')
rightCount++;
}
}
else
{
int j = 0;
for(; j < i ; ++j)
{
if(s[j] == '0')
leftCount++;
}
++j;
for( ; j < sz ; ++j)
{
if(s[j] == '0')
rightCount++;
}
}
ans += leftCount*rightCount;
}
return ans;
}
};
2.动态规划
遍历字符串s的过程中,统计 1 ,10 , 0 ,01的个数,并不断地更新。
例如: s[ i ] = 1, 以1结尾只能组合成 101,结果+= 10的个数,ans += Count(10) ; 1的个数增加 1, 因为s[ i ] = 1,多了一个 1, 那么 01的个数需要 增加(+=) 0的个数 。
s[ i+1 ] = 0 , 以0结尾只能组合成 010 , 结果 += 01的个数 , ans += Count(01) ; 0的个数增加1 ,因为s[ i+1 ] = 0 , 多了一个0,那么10的个数需要增加(+=) 1的个数。
代码:
class Solution {
public:
long long numberOfWays(string s)
{
long long ans=0, n0=0, n1=0, n10=0, n01=0;
for(size_t i=0; i<s.size(); i++)
{
/*
循环不变式(loop invariant)
n0 等于 s.substr(0,i)中 值为 "0" 的子序列的数量
n1 等于 s.substr(0,i)中 值为 "1" 的子序列的数量
n10 等于 s.substr(0,i)中 值为 "10" 的子序列的数量
n01 等于 s.substr(0,i)中 值为 "01" 的子序列的数量
对于新增的字符s[i], 讨论以s[i]结尾的所有新增子序列, 然后更新n0,n1,n10,n01
*/
if(s[i] == '1') //新增是1
{
n01 += n0;
n1 ++;
ans += n10; //左边10 + 1变成了101,成立
}
else
{
n10 += n1;
n0 ++;
ans += n01; //左边 01 + 0变成了010,成立
}
}
return ans;
}
};
3.两次遍历
①遍历一次s , 统计0 和 1 的个数;
②int left_one , 统计某个数左边0的个数 ,int left_zero ,统计某个数左边1的个数 ,从第二个元素开始(第一个数左边为空和最后一个数右边为空),如果该数是0 ,ans+= left_one * (one_num - left_one); left_zero++; 如果该数是1 ans += left_zero * (zero_num - left_zero); left_one++;
③巧妙的利用0 和 1 的个数进行计算。
class Solution {
public:
long long numberOfWays(string s)
{
int size = s.size();
int one_num = 0;
int zero_num = 0;
for(int i = 0 ; i < size ;++i)
{
if(s[i] == '0')
{
zero_num++;
}
else
{
one_num++;
}
}
int left_one = 0; //统计左边0的个数
int left_zero = 0; //统计左边1的个数
if(s[0] == '0')
{
left_zero++;
}
else
{
left_one++;
}
long long ans = 0;
for(int i = 1 ; i < size-1 ;++i) //第一个和最后一个不用
{
if(s[i] == '0')
{
ans += left_one * (one_num - left_one);
left_zero++;
}
else
{
ans += left_zero * (zero_num - left_zero);
left_one++;
}
}
return ans;
}
};