本人电子系,只为一学生。心喜计算机,小编以怡情。
给出两个32位的整数N和M,以及两个二进制位的位置i和j。写一个方法来使得N中的第i到j位等于M(M会是N中从第i为开始到第j位的子串)
样例
给出N = (10000000000)2,M = (10101)2, i = 2, j = 6
返回 N = (10001010100)2
感悟:
1.原本以为很简单的事情,但是如果对二进制的原码补码运算不熟悉,会有很多坑,比如测试数据里有-1,补码表示是11111111111111111111111111111111。
2.然后就是各种下表越界,各种debug。
3.然后发现自己对Java的库了解太少,应该有更方便的内置函数,但我并不知道。。。
思路:将n中要替换的部分减去,得到类似二进制xxxxx0000xxxx的效果
然后将m加到上面,比如1011变成1011xxxx,再加到n上,得到的就是答案。
public int updateBits(int n, int m, int i, int j) {
// write your code here
///////////////////////////////////
// 得到1011xxxx的效果
for(int k=0;k<i;k++)
m*=2;
///////////////////////////////////
//将n,m转成二进制表示
StringBuffer temp1=new StringBuffer(Integer.toBinaryString(n));
StringBuffer temp2=new StringBuffer(Integer.toBinaryString(m));
///////////////////////////////////
// 因为下面要给字符串前面补零,因此提前保存相关长度
int r=temp1.length();
int t=j-i+1;
///////////////////////////////////
// 只有整数需要补零
//补零的原因是为了解决当n=1,m=1011,i=2,j=5时,
//接下来下面的substring提取子串会报错(下标)
//当然,你也可以用其他的更好的方法,比如动态补零,或者干脆不补零
//用其他的方法
if(n>=0)
for(int k=0;k<32-r;k++)
temp1.insert(0, "0");
if(m>=0)
for(int k=0;k<32-t;k++)
temp2.insert(0, "0");
///////////////////////////////////
//这一步就是提取n中要被取代的那部分子串,然后左移(尾部补零)
StringBuffer a=new StringBuffer(temp1.substring(temp1.length()-i-t, temp1.length()-i));
for(int k=0;k<i;k++)
a.append("0");
//// ///////////////////////////////
//你可以用int试一试,测试某个数据会报错
int count=0;
long sum=0;
///////////////////////////////////
//这里应该有简便的函数 ,将二进制字符串转化为十进制int型
for(int k=a.length()-1;k>=0;k--)
{
sum+=Math.pow(2, count++)*Integer.parseInt(a.charAt(k)+"");
}
///////////////////////////////////
//返回就是n-要被替代的那部分+m
return (int) (n-sum+m);
}