1702. 修改后的最大二进制字符串 ●●
描述
给你一个二进制字符串 binary ,它仅有 0 或者 1 组成。你可以使用下面的操作任意次对它进行修改:
操作 1 :如果二进制串包含子字符串 “00” ,你可以用 “10” 将其替换。
比方说, " 00 010 " -> " 10 010 "
操作 2 :如果二进制串包含子字符串 “10” ,你可以用 “01” 将其替换。
比方说, " 000 10 " -> " 000 01 "
请你返回执行上述操作任意次以后能得到的 最大二进制字符串 。如果二进制字符串 x 对应的十进制数字大于二进制字符串 y 对应的十进制数字,那么我们称二进制字符串 x 大于二进制字符串 y 。
示例
输入:binary = “000110”
输出:“111011”
解释:一个可行的转换为:
“000110” -> “000101”
“000101” -> “100101”
“100101” -> “110101”
“110101” -> “110011”
“110011” -> “111011”
题解
1. 贪心算法
10 变 01 其实是把1往后挪一位,是亏的,
想要变大还得结合 00 变 10,这样是赚的。
- 要保证数字最大,首先考虑 左侧连续的 “1” 是不需要移动的
- 因为可以 “10” -> “01” 变换,所以可以将除 左侧连续的 “1” 之外其他的 “1” 全都移到最右侧
这样处理之后,数据变为 左侧连续的 “1”,右侧连续的 “1” ,和 中间连续的 “0” - 然后通过 “00” -> “10” 将 中间连续的 “0” 变换
即 “000…000” -> “111…110”(连续 0 的最后一位变换后依然为 0)
这样整个数字最终就是 “111…11011…111” ,即两侧是连续的 “1” 中间一个 “0” 的情况 - 最后,只需要计算出 “0” 是第几位,进而就可以得到最大的数字
- 按这个思路的代码,还需要考虑处理全 “1” 的情况
- 时间复杂度:O(n)
- 空间复杂度:O(1)
@lkaruga
class Solution {
public:
string maximumBinaryString(string binary) {
int n = binary.length();
int zero_start = n-1;
for(int i = 0; i < n; ++i){
if(binary[i] == '0'){
zero_start = i; // 非连续1的开头位置
break;
}
}
if(zero_start == n-1) return binary; // 字符串全 1 的情况
int one_cnt = 0;
for(int i = zero_start; i < n; ++i){
if(binary[i] == '1') ++one_cnt; // 最右边 1 的个数
binary[i] = '1';
}
binary[n-one_cnt-1] = '0'; // 00 -> 10 之后0的位置
return binary;
}
};