查找字符串可以减少到 0 的步骤数
Find the number of steps a string can be reduced to 0
我的作业:
您将获得一个非负整数变量 $Z$。有两个操作可以更改其值:
如果 $Z$ 是奇数,则从中减去 1;
如果 $Z$ 是偶数,则将其除以 2。
执行这些操作,直到 $Z$ 的值变为 0。
你必须编写一个函数:
int solution(string &S);
这样,当给定一个由 $N$ 字符组成的字符串S
时,该字符串包含变量 $Z$ 初始值的二进制表示形式,返回步数 之后,如上所述,$Z$ 的值将变为 0。
#include<iostream>
int solution(string &S) {
int x = stoi(S, 0, 2);
int count = 0;
while (x != 0) {
if (x % 2 == 0) {
x /= 2;
count++;
} else {
x -= 1;
count++;
}
}
return count;
}
现在,这段代码的时间复杂度爆炸了。在编写有效的解决方案时,我哪里出错了?
现在这段代码的时间复杂度爆炸了。在编写有效的解决方案时,我哪里出错了?
您不应该将字符串转换为数字,因为它可能太长而无法容纳32-bit
甚至64-bit
整数。相反,您应该意识到的是,我们所知道的只是1
onesCount
的数量和整数字符串的长度size
(我们假设每个问题陈述没有前导零(。让我们考虑一个例子。假设我们有一个数字11001
.然后,可以按如下方式说明步骤:
1 1 0 0 1 subtract rightmost bit because it's 1
|
v
1 1 0 0 0 right shift because rightmost 0
|
V
0 1 1 0 0 right shift because rightmost 0
|
v
0 0 1 1 0 right shift because rightmost 0
|
v
0 0 0 1 1 subtract rightmost bit 1
|
v
0 0 0 1 0 right shift because rightmost 0
|
V
0 0 0 0 1 subtract rightmost bit 1
|
V
0 0 0 0 0 Complete.
因此,如您所见,如果最右边的数字是0
的(并且左侧仍有1
(,那么移动到下一个右边的数字需要一步。但是,如果最右边的数字是1
(它不是最后一个(,那么我们需要2
的步骤 - 将其作废并移动到下一个右数字。显然,如果最左边的数字是1
并且它是最后一个,那么它只是一个步骤。
但是,步骤数可以表示为:
- 如果
0
一个数字,则步数也0
。 - 如果只有一次出现
1
则步骤数为字符串的size
。 - 如果出现更多
1
,则总步数onesCount * 2 + (size - onesCount - 1)
。但是,这比第 2 节更通用,我们可以将其用于这两种情况。
法典
uint32_t solveMe(std::string &number) {
uint32_t onesCount = std::count(number.begin(), number.end(), '1');
if (onesCount == 0) {
return 0;
}
uint32_t numberSize = number.size();
return onesCount * 2 + (numberSize - onesCount - 1);
}
更新
正如@lucieon所指出的,另一种看待这个问题的方式可以用下面的公式来描述:
zerosCount + (onesCount-1)*2 + 1
这是我在 C# 中的解决方案,它涵盖了使用前导零的可能性。 涵盖"00011101"等情况。
public class Solution
{
public static int EfficientCountStepsToZero(string S)
{
var newString = RemoveLeadingZeros(S);
int zerosCount = 0;
int onesCount = 0;
for (int i = 0; i < newString.Length; i++)
{
if (newString[i] == '0')
{
zerosCount++;
}
else
{
onesCount++;
}
}
return zerosCount + (onesCount - 1) * 2 + 1;
}
private static string RemoveLeadingZeros(string S)
{
char[] letter = S.ToCharArray();
for (int i = 0; i < letter.Length; i++)
{
if (letter[i] == '1')
{
break;
}
letter[i] = ' ';
}
return new string(letter).Trim();
}
}
//您也可以使用导入,例如: 导入 java.util.*;
您可以写入 stdout 进行调试,例如 System.out.println("This is a debug message"(;
类解决方案 {
private static String RemoveLeadingZero(String xx)
{
char[] letter = xx.toCharArray();
for (int i = 0; i < letter.length; i++)
{
if (letter[i] == '1')
{
break;
}
letter[i] = ' ';
}
String ans = new String(letter);
return ans.trim();
}
public int solution(String S) {
// write your code in Java SE 11
String xy = RemoveLeadingZero(S);
int zeroCount = 0;
int oneCount = 0;
int f= xy.length();
for (int i = 0; i < f; i++)
{
if (xy.charAt(i) == '0')
{
zeroCount++;
}
else
{
oneCount++;
}
}
return zeroCount + (oneCount - 1) * 2 + 1;
}
}
这是我在 Kotlin 中的解决方案,希望对您有所帮助:
private fun RemoveLeadingZero(xx: String): String {
val letter = xx.toCharArray()
for (i in letter.indices) {
if (letter[i] == '1') {
break
}
letter[i] = ' '
}
val ans = String(letter)
return ans.trim { it <= ' ' }
}
fun solution(S: String): Int {
val xy = RemoveLeadingZero(S)
var zeroCount = 0
var oneCount = 0
val f = xy.length
for (i in 0 until f) {
if (xy[i] == '0') {
zeroCount++
} else {
oneCount++
}
}
return zeroCount + (oneCount - 1) * 2 + 1
}
- 使用正则表达式regex_search在字符串中查找字符串
- 按类型与字符串查找对象
- 使用C RTTI(内置)通过字符串查找功能指针
- 关于获取行和字符串查找函数的问题
- 字符串查找方法找不到第一字母
- C++ 字符串.查找()
- 遇到字符串::查找的问题
- 将一个数组作为子字符串查找到另一个数组中
- 字符串查找第一个非的 C++ 问题
- 如何将通配符与字符串::查找一起使用
- 字符串::查找问题 (C++)
- 性能标准::strstr vs. 标准::字符串::查找
- C++字符串::查找崩溃应用程序
- 使用字符串查找单词的正确方法是什么
- 如何在<string>没有 std::string 中介的情况下制作一个支持通过 C 字符串查找的集合?
- 使用C++根据行中的第一个字符串查找行(仅一个)
- Borland字符串::查找bug
- std::map如何通过字符串查找元素
- 字符串查找函数返回奇数
- 如何使用子字符串查找数字行的正确部分