题目描述
实现思路1
暴力解,两层循环,外层循环模拟分割线的运动,内层两个循环计算0和1的个数'
代码实现
class Solution {
public int maxScore(String s) {
int len = s.length();
int score = 0;
int ans = 0;
for (int i = 1; i < len; i++) {
score = 0;
for (int j = 0; j < i; j++) {
if(s.charAt(j) == '0'){
score++;
}
}
for (int j = i; j < len; j++) {
if(s.charAt(j) == '1'){
score++;
}
}
ans = Math.max(ans, score);
}
return ans;
}
}
时间效率O(n^2);
实现思路2
先计算从下标1开始的字符是否为1,若为1,则加分(从1开始是因为分隔字符串必须有左右两半,所以还要判断下标0是否是1)。该思路简单理解即为,先计算分割线为下标1时的得分,后面再接着循环模拟分割线的移动情况,若在分割线地方的为0,表示左边+1分,若分割线地方为1,表示右边-1分
代码实现
class Solution {
public int maxScore(String s) {
int len = s.length();
int score = 0;
if(s.charAt(0) == '0')
score++;
for (int i = 1; i < len; i++) {
if(s.charAt(i) == '1')
score++;
}
int ans = score;
for (int i = 1; i < len - 1; i++) {
if(s.charAt(i) == '0')
score++;
else
score--;
ans = Math.max(ans, score);
}
return ans;
}
}
时间复杂度O(n)
空间复杂度O(1)
实现思路3(学至宫水)
思路与思路2相类似,但是使用数组记录每个分割线的前半部分1的数量,有一点点动态规划的思想.
然后就类似于暴力,通过移动分割线,计算机在分割线前后的0和1的数量,因为有数组记录着该分割线前的1的数量,使用不需要遍历计算,节省时间.
class Solution {
public int maxScore(String s) {
int n = s.length(), ans = 0;
int[] sum = new int[n + 10];
for (int i = 1; i <= n; i++){
//通过遍历和动态规划,找到在下标前有多少个1
sum[i] = sum[i - 1] + (s.charAt(i - 1) - '0');
}
for (int i = 1; i <= n - 1; i++) {
//在这个下标处记录着该下标前多少个1,通过相减,得出前半0的个数
int a = i - sum[i];
//sum[n]记录着1的总数,相减后,得出后半1的个数
int b = sum[n] - sum[i];
ans = Math.max(ans, a + b);
}
return ans;
}
}