您好我正在解决问题:
给定一个基数为10的整数n,将其转换为二进制(base-2)。然后找到并且 打印基数为10的整数,表示连续1的最大数量 在n的二进制表示中。对于例如对于n = 5,base-2 = 101所以输出应该是1,对于n = 439,base-2 = 110110111,所以输出应该是3.
以下是我的代码解决方案:
class Solution {
static int CalcBinary (int n) {
Stack<int> binRep = new Stack<int>();
while (n > 0) {
int i = n%2;
binRep.Push (i);
n = n/2;
}
int oldCount = 0, newCount = 0;
while (binRep.Count > 0){
int val = binRep.Pop();
if (val == 1) {
newCount++;
} else {
if (newCount > oldCount) {
oldCount = newCount;
}
newCount = 0;
}
}
return (newCount > oldCount) ? newCount : oldCount;
}
static void Main(String[] args) {
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine (CalcBinary(n));
}
}
代码运行良好并通过所有测试用例,例如n = 5,6,439等。只有问题是,如果有任何优化的解决方案来做同样的事情。其他人发布了相同的问题here,但对该问题的所有回复似乎与O(n)时间复杂度相同。另一件事是我可以使用数组而不是Stack,但它会有什么不同吗?
答案 0 :(得分:5)
public int CalcBinary(int n)
{
int result = 0;
int current = 0;
for (int i = 0; i + result < 32 && (n >> i) != 0; i++)
{
if (((n >> i) & 1) == 1)
current += 1;
else
{
if (current > result)
result = current;
current = 0;
}
}
return result == 0 ? current : result;
}
我不太擅长大O算术,但我认为这个解决方案应该更快,因为我不使用任何其他类而是简单的位移。
如果不再有解决方案,我提前停止(i + result < 32
)。
注意,这仅适用于 32位整数。对于64位调整上述条件。它仅适用于正值(设置符号位可能会产生错误的结果,例如111....111101
)。
更新:根据@ Scott-Chamberlain的建议添加了(n >> i) != 0
条件(它会检查是否还有1
个。)
答案 1 :(得分:2)
为什么不在转换二进制文件而不是等待转换完成时计算maximum_consecutive
,然后再从堆栈中计算maximum_consecutive
?
我认为你应该改变这一点。
class Solution {
static int CalcBinary (int n) {
int oldCount = 0, newCount = 0;
while (n > 0) {
int i = n%2;
n = n/2;
if (i == 1) {
newCount++;
}
else {
if (newCount > oldCount) {
oldCount = newCount;
}
newCount = 0;
}
}
return (newCount > oldCount) ? newCount : oldCount;
}
static void Main(String[] args) {
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine (CalcBinary(n));
}
}
答案 2 :(得分:1)
对于有点小小的乐趣和最小的分支:
int[] lookup = new[]
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
int LongestRunOfBits(uint value)
{
int max = 0;
while(1 << max < value + 1)
{
uint testValue = ~value;
uint lookupIndex = ((uint)((testValue & -testValue) * 0x077CB531U)) >> 27;
int trailingZeros = lookup[lookupIndex];
max = trailingZeros - ((trailingZeros - max) & ((trailingZeros - max) >> 31));
value >>= 1;
}
return max;
}
这结合了以下操作:
Compute the maximum of two integers without branching(QuAD版本)
Count the consecutive zero bits (trailing) on the right with multiply and lookup(如果它计算value
上的尾随零位,则计算~value
上的一位尾随
让我们按照value
6或110
进行此操作:
现在我们有:
value : 00000000000000000000000000000110 ~value : 11111111111111111111111111111001 trailing zero bits : 0 value after rsh : 00000000000000000000000000000011 ~value : 11111111111111111111111111111100 trailing zero bits : 2 value after rsh : 00000000000000000000000000000001 //skip this last iteration ~value : 11111111111111111111111111111110 //as it will now be impossible trailing zero bits : 1 //to find a value > 2
通过查找~value
的尾随零位的最大数量,我们有效地找到value
的最后一位尾随位数。如果我们继续进行右移,直到没有剩余比特,则最长的设置比特运行是我们在~value
上执行的尾随零比特操作的最大值。万岁。一旦我们找到值2并且值中剩余2个或更少的位,我们可以提前保释,因为我们可以确定不会找到大于2的值,因此可以跳过最后一次迭代。