如何为整数(相同数量的1)找到下一个较低的二进制数?例如:如果给定输入数n = 10(1010),则函数应返回9(1001),或n = 14(1110)然后返回13(1101),或n = 22(10110)然后返回21(10101) ,n = 25(11001)然后返回22(10110)......等等。
答案 0 :(得分:3)
你可以这样做。
static int nextLower(int n) {
int bc = Integer.bitCount(n);
for (int i = n - 1; i > 0; i--)
if (Integer.bitCount(i) == bc)
return i;
throw new RuntimeException(n+" is the lowest with a bit count of "+bc);
}
当然,如果这是家庭作业,你将无法说服你写这篇文章的人;)
答案 1 :(得分:2)
为了清楚起见,在这个答案中,我将使用术语“基数”来表示数字的二进制表示中的1的数量。
一种(显而易见的)方法是运行向下循环,并寻找具有与输入相同基数的第一个数字(就像Peter Lawrey建议的那样)。
我不认为这是低效的,因为我猜输出数总是非常接近输入。更准确地说,您所要做的就是找到最右边的“10”位序列,并将其更改为“01”。然后在不破坏后置条件的情况下,尽可能多地将右侧部分替换为左侧全部为1的数字。这将我们带到另一个解决方案,其中包括将数字转换为二进制字符串(如user2573153显示),执行替换(可能使用正则表达式),然后转换回int。
Peter的算法稍微快一点的版本应该是以下内容,它对整数执行我为字符串提出的操作:
static int nextLower(int n) {
int fixPart = 0;
int shiftCount = 0;
while ((n & 3) != 2) {
if (n == 0) {
throw new IllegalArgumentException(
fixPart + " is the lowest number with its cardinality");
}
fixPart |= (n & 1) << shiftCount;
shiftCount += 1;
n /= 2;
}
int fixZeros = shiftCount - Integer.bitCount(fixPart);
return ((n ^ 3) << shiftCount) | (((1 << shiftCount) - 1) & ~((1 << fixZeros) - 1));
}
是O(log n)而不是O(n),但由于其复杂性,它肯定更难理解,并且实际上也可能更慢。无论如何,如果你尝试使用一些巨大的数字,你只能注意到差异。
答案 2 :(得分:1)
我喜欢这样的二进制任务,所以要找到下一个较低的数字,你应该找到最正确的1然后是0并交换它们。更新:你需要“重新排序”数字的剩余部分,左边是1,右边是0
10 1010 ->
9 1001
14 1110 ->
13 1101
25 11001 ->
22 10110
这是示例代码:
int originalValue = 25;
int maskToCheck = 2; // in binary 10b
int clearingMask = 1;
int settingMask = 0;
int zeroCount = 0;
while (maskToCheck > 0)
{
if ( (originalValue&(maskToCheck|(maskToCheck>>1))) == maskToCheck ) // we found such
{
int newValue = originalValue&(~maskToCheck); // set 1 with 0
newValue = newValue&(~clearingMask)|(settingMask<<zeroCount); // clear all the rest bits, and set most valuable ones
newValue = newValue|(maskToCheck>>1); // set 0 with 1
System.out.println("for " + originalValue + " we found " + newValue);
break;
}
else
{
if ( (originalValue&(maskToCheck>>1)) > 0) // we have 1 bit in cleared part
settingMask = (settingMask<<1) | 1;
else
zeroCount++;
maskToCheck = maskToCheck<<1; // try next left bits
clearingMask = (clearingMask<<1)|1;
}
}