开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
问题描述
给你一个二进制字符串 s 。在一秒之中,所有 子字符串 "01" 同时 被替换成 "10" 。这个过程持续进行到没有 "01" 存在。
请你返回完成这个过程所需要的秒数。
示例 1:
输入: s = "0110101"
输出: 4
解释:
一秒后,s 变成 "1011010" 。
再过 1 秒后,s 变成 "1101100" 。
第三秒过后,s 变成 "1110100" 。
第四秒后,s 变成 "1111000" 。
此时没有 "01" 存在,整个过程花费 4 秒。
所以我们返回 4 。
示例 2:
输入: s = "11100"
输出: 0
解释:
s 中没有 "01" 存在,整个过程花费 0 秒。
所以我们返回 0 。
提示:
1 <= s.length <= 1000s[i]要么是'0',要么是'1'。
进阶:
你能以 O(n) 的时间复杂度解决这个问题吗?
思路分析
首先我们要先理解一下题目意思,题目会给我们一个只包含0和1的字符串,我们需要对字符串进行调整,将字符串中所有的01替换成10,直到字符串中不包含01子串为止,每一次替换会消耗1秒钟的时间,我们需要计算整个调整过程需要消耗多少时间。
- 正则替换
首先我们最容易想到的肯定是直接暴力替换,我们可以直接使用正则来替换整个字符串,替换完之后再次判断字符串中是否还包含01字符串,如果还存在,则需要再次替换。
let res = 0;
while(s.indexOf('01') != -1){
s = s.replace(/01/g,'10');
res++;
}
- 遍历计算
当然,我们也可以通过一次遍历来求出答案,我们再次分析一下题目,可以发现,题目的本质其实就是要将字符串中所有的1都移动到最左方,移动时间主要由以下两个因素影响:
1、需要移动元素前面0的个数
2、需要移动元素前面连续1的个数
要将当前位置的1移到最左方,因为每次移动需要和前一个相邻的0进行位置交换,所以其最少移动的次数应该为前面0的个数,而遇到连续1的时候,需要等待前一个1先往前移动腾出空位后当前位置的1才能继续往左移动,而且当前位置的1的移动次数至少应该是前一个1的移动次数加一。
let res = 0,zero = 0;
for(let i = 0; i < s.length; i++){
if(s[i] == '0'){
zero++;
}
else if(zero > 0) res = Math.max(res + 1,zero);
}
AC代码
完整代码如下:
/**
* @param {string} s
* @return {number}
*/
var secondsToRemoveOccurrences = function(s) {
let res = 0,zero = 0;
for(let i = 0; i < s.length; i++){
if(s[i] == '0'){
zero++;
}
else if(zero > 0) res = Math.max(res + 1,zero);
}
return res;
};
说在后面
本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。