在一个测试用例上更新位错误

时间:2015-06-21 06:50:36

标签: java algorithm bit-manipulation

给定两个32位数字,N和M,以及两个位,i和j。写一个方法来设置i和j之间的所有位在N中等于M(例如,M变成N的子串,位于i并从j开始)

实施例

Given N=(10000000000)2, M=(10101)2, i=2, j=6
return N=(10001010100)2

这是我的代码:

class Solution {
/**
 *@param n, m: Two integer
 *@param i, j: Two bit positions
 *return: An integer
 */
public int updateBits(int n, int m, int i, int j) {
    n = clearbits(n,i,j);
    m = m<<i;
    return m|n;
}
public static int clearbits(int n, int i, int j){
    //& with 0
    long allones = ~0;
    long left = allones << (j);
    long right = ((1<<i) - 1);
    long mask  = left | right;
    return (int) mask & n;
}}

问题是输入[-123,45,21,26]预期输出为-37748859,代码提供输出-123

更新:更改clearbits后处理整数溢出。它无法进行以下输入  输入 [-521,0,31,31] 产量 -521 预期 2147483127

1 个答案:

答案 0 :(得分:3)

你真正需要的是:

public int updateBits(int n, int m, int i, int j) {
  int mask = ((int)((1L<<(j-i+1))-1))<<(i);
  return (n&~mask)|((m<<i)&mask);
}

请注意,出于调试目的,您可以使用以下方法打印出位字符串:

System.out.println(Integer.toBinaryString(mask));

基本上我需要创建一个与ij之间的位位置匹配的掩码。现在假设我想在位置3和5之间进行掩码,我基本上想要生成一个如下所示的掩码:

0000111000

我可以先尝试生成这个:

0000000111

i位置向左移动。这个值+ 1给了我:

0000001000

哪个是1 << (j-i+1),并且在(1 << (j-i+1))-1中减去一个给我的面具我还需要进一步左移i,所以我得到了掩码:

((1<<(j-i+1))-1)<<(i)

使用(n&~mask)完成n上的清除位。

我无法直接屏蔽m中的位,因为我仍然需要左移它,以便它匹配要替换的位串的位置。转移后,我可以使用((m<<i)&mask)进行掩码。请注意,如果用户确保m适合掩码,则可能不需要屏蔽m

现在把两个术语放在一起,你就得到了答案!

return (n&~mask)|((m<<i)&mask);

或者没有屏蔽m,您可以一步完成:

return (n&~(((int)((1L<<(j-i+1))-1))<<(i)))|(m<<i);

更新:

您可以采用稍微不同的方法,在此处构建蒙版的左侧和右侧,并将两者一起添加。好方法。但是,我注意到的一个错误是:左边不应该是allones << (j+i)而只是allones << (j+1)(加上一个,而不是加i)。

我们还需要再次关注溢出:

int left = (int)(((long)allones) << (j+1));