问题陈述如下:
给定数字x,找到大于或等于x的最小稀疏数 如果在其二进制表示中没有两个相邻的1,则数字是稀疏的。例如5(二进制表示:101)是稀疏的,但是6(二进制表示:110)不是稀疏的。
我从this post处理问题,其中列出了最有效的解决方案,其运行时间为O(logn):
1)找到给定数字的二进制数并将其存储在a中 布尔数组。 2)将last_finalized位的初始化为0。 2)开始从最低有效位遍历二进制。 a)如果我们得到两个相邻的1,那么下一个(或第三个) 比特不是1,那么 (i)在此1之后使所有位最后完成 位(包括最后确定的)为0。 (ii)将最后完成的位更新为下一位。
帖子中没有明确的含义是"最终的位。"似乎算法首先通过使用while循环将数字的二进制表示插入std::vector
来开始,其中它将输入(数字x)与1进行ANDS然后将其推回到向量中但是至少从提供的描述中,不清楚为什么这样做。 是否有更明确的解释(甚至方法)来解决此问题的有效解决方案?
修改
// Start from second bit (next to LSB)
for (int i=1; i<n-1; i++)
{
// If current bit and its previous bit are 1, but next
// bit is not 1.
if (bin[i] == 1 && bin[i-1] == 1 && bin[i+1] != 1)
{
// Make the next bit 1
bin[i+1] = 1;
// Make all bits before current bit as 0 to make
// sure that we get the smallest next number
for (int j=i; j>=last_final; j--)
bin[j] = 0;
// Store position of the bit set so that this bit
// and bits before it are not changed next time.
last_final = i+1;
}
}
答案 0 :(得分:3)
如果在数字的二进制表示中看到任何序列“011”,则将“0”更改为“1”并将其后的每一位设置为“0”(因为它给出了最小值)。
该算法建议从右侧(最低位)开始,但如果从左侧开始,找到最左侧的序列“011”,并按上述方式执行,您将获得解决方案的一半时间。另一半是当该序列左边的下一位为'1'时。当您将'0'更改为'1'时,您创建一个需要以相同方式处理的新“011”序列。
“最后确定的位”是最左边的'0'位,其右侧仅看到'0'位。这是因为所有这些'0'都不会在接下来的步骤中改变。
答案 1 :(得分:0)
所以这里有一些观察来解决这个问题:-
现在将数字转换为二进制格式,如果最后一位数字是 0,那么我们可以在末尾附加 1 和 0,但如果最后一位数字是 1,那么我们只能在末尾附加 0。 所以天真的方法是做一个简单的迭代并检查每个数字,但如果我们仔细观察一些例子,我们可以优化这种方法
let say n=5 -> 101 next sparse is 5 (101)
let say n=14 -> 1110 next sparse is 16 (10000)
let say n=39 ->100111 next sparse is 40 (101000)
let say n=438 -> 110110110 next sparse is 512 (1000000000)
为了优化简单的方法,这里的想法是使用 BIT-MANIPULATION 这个概念是,如果我们将一个位序列与其自身的移位版本进行 AND 运算,我们就可以有效地从每个连续 1 的序列中删除尾随的 1。
for n=5
0101 (5)
& 1010 (5<<1)
---------
0000
因此,当您将 n&(n<<1) 的值设为零时,意味着您拥有的数字中没有任何连续的 1(因为如果它不为零,则必须有一系列连续的 1)我们的号码)所以这将是答案
for n=14
01110 (14)
& 11100 (14<<1)
----------------
01100
所以值不为零,然后将我们的数字增加 1,所以我们的新数字是 15 现在再次执行相同的操作
01111 (15)
& 11110 (15<<1)
------------------------------
01110
再次我们的数字不为零,然后将数字增加 1 并在 n = 16 时执行相同的操作
010000 (16)
& 100000 (16<<1)
------------------------
000000
所以现在我们的数字变为零,所以我们现在遇到一个不包含任何连续 1 的数字,所以我们的答案是 16。
因此,您也可以以类似的方式检查其他号码。 希望你明白了,如果是这样,然后upvote。快乐编码!
int nextSparse(int n) {
// code here
while(true)
{
if(n&(n<<1))
n++;
else
return n;
}
}
时间复杂度为 O(logn)。