问题陈述: 找到从0(零)到达目标数x所需的最小步数,仅使用两个操作:+ 1 (对数字加1)或* 2 (乘以2数字)。
所以这就是我提出的逻辑:
最好的方法是倒退。从您需要的号码开始:
例如,对于29,你得到28,14,7,6,3,2,1,0。
而且,这是我尝试过的(Java 7):
kValues
是一个数组,其x
值需要计算steps
并存储在名为result
的数组中。
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,x,i,steps;
int result[] = new int[size];
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = (int)kValues[i]; x != 0 ; ++steps)
{
if((x % 2) == 0)
x /= 2;
else x--;
}
result[i] = steps;
}
return result;
}
我的问题:
这是一个Hackerrank问题,我应该写一个有效的代码。我在7/11测试用例中取得了成功,其他人则超时了。既然,这是一个Hackerrank问题,我无法更改函数定义或返回类型。这就是我在long
循环中从int
转换为for
的原因,以便使用%
(模数)。我想知道我哪里出错了。我的算法计算时间太长(对于接近一百万的值的数量)?显然是这种情况,但如何更改算法以通过所有测试用例?
提前谢谢你:)
答案 0 :(得分:1)
for (x = (int)kValues[i]; x != 0 ; ++steps)
你向int转换一个长的事实是非常可疑的。当你这样做时,你可能得到一个负数。
说出x == -2
:您将其除以2以得到-1
,然后减去1得到-2
。你会无限期地继续这样做。
只需将x
定义为long
,然后移除演员。
答案 1 :(得分:0)
所以,这是工作代码。我忘了在使用模数时附加L
。愚蠢的错误导致了很多打字。 LOL !!
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,i,steps;
int result[] = new int[size];
long x;
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = kValues[i]; x != 0 ; ++steps)
{
if((x % 2L) == 0)
x /= 2L;
else x -= 1L;
}
result[i] = steps;
}
return result;
}
答案 2 :(得分:0)
这是一个非常短的版本,使用位分析:
static int[] countOperationsToK(long... input) {
int result[] = new int[input.length];
for (int i = 0; i < input.length; i++)
if (input[i] > 0)
result[i] = Long.bitCount(input[i]) + 63 - Long.numberOfLeadingZeros(input[i]);
return result;
}
这里的想法是查看二进制数,例如对于29 11101
。有4位设置,所以我们需要做+1
四次,最高位位是4,所以我们需要左移(即*2
)四次,总共8个操作:+1
,*2
,+1
,*2
,+1
,*2
,*2
,{{1} }。
+1
如果值为零,则numberOfBits = Long.bitCount(x)
highBitNumber = floor(log2(x)) = 63 - Long.numberOfLeadingZeros(x)
部分不起作用,因此highBitNumber
语句。
答案 3 :(得分:0)
对于输入数字x,
最小编号操作数=(int)log2(x)+ Long.BitCount(x)