题意理解
对于一个二进制字符串,我们只有一次机会选择其中一段连续的区间,将其中每个字符取反(即0变为1,1变为0),当然也可以不更新字符串。我们希望最后得到的字符串表示的数字最大。
方法一
暴力枚举
使用双重循环,列举出所有取反的可能性,并从中去最大值。由于是连续反转的,反转操作和确定反转的右边界可以公用一个循环。
具体代码如下:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num string字符串
* @return string字符串
*/
string maxLexicographical(string num) {
// write code here
string maxm = num;
//遍历反转的起始位置
for (int i=0;i<num.size();i++)
{
string ss = num;
//遍历反转的长度
for (int j=i;j<num.size();j++)
{
if (ss[j]=='1') ss[j] = '0';
else ss[j] = '1';
//判断大小
if (ss > maxm) maxm = ss;
}
}
return maxm;
}
};
时间复杂度: 。使用了双重循环。
空间复杂度: 。使用了两个字符串分别记录最大值和当前反转后的字符串。
方法二
注意到二进制字符串左侧为高位,右侧为低位。为了使数字更大,我们要把最左侧的第一个0改为1。除此之外,我们还注意到,最高位为1后面全为0,是大于最高位为0后面全为1的(例如100大于011),所以我们不会为了后面存在大量的0而改变当前位置上的1。
我们的过程为,从左往右遍历字符串,遇到第一个0时将其改为1,并继续向右遍历,如果一直为0就该位改为1并继续遍历;一旦遇到了1就结束程序。
过程的示意图如下:
具体代码如下:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param num string字符串
* @return string字符串
*/
string maxLexicographical(string num) {
// write code here
for (int i=0;i<num.size();i++)
{
//找到第一个‘0’
if (num[i]=='0')
{
int l = i;
num[i] = '1';
while ((l+1<num.size()) && num[l+1]=='0')
{
l++;
num[l] = '1';
}
//注意这里在while结束后就要break跳出for循环
break;
}
}
return num;
}
};
时间复杂度: 。将字符串遍历了一遍。
空间复杂度: 。没有开辟新的存储空间。