来源:力扣(LeetCode)
链接:面试题 05.01. 插入
有关移位运算符
左移运算符:<<
不区分正负数,左移之后在右边补0, 相当于num乘以2
public class test {
public static void main(String[] args) {
int A = 8;
System.out.println("A : " + Integer.toBinaryString(A));
int M, N;
M = A << 1;
System.out.println("M : " + M);//相当于乘以2
System.out.println(Integer.toBinaryString(M));
N = A << 2;
System.out.println("N : " + N);//相当于乘以4
System.out.println(Integer.toBinaryString(N));
}
}
A : 1000
M : 16
10000
N : 32
100000
右移运算符:>>
右移之后在左边补上符号位,正数补0,负数补1,相当于num除以2
无符号右移:>>>
无论该数为正还是为负,右移之后左边补0
>> 与 >>> 对比:
public class test {
public static void main(String[] args) {
int A = -5;
System.out.println(Integer.toBinaryString(A));
System.out.println(Integer.toBinaryString(A >> 1));
System.out.println(Integer.toBinaryString(A >>> 1));
System.out.println(Integer.toBinaryString(A >> 2));
System.out.println(Integer.toBinaryString(A >>> 2));
}
}
11111111111111111111111111111011//A
11111111111111111111111111111101//A>>1,负数:在左边补符号位1
1111111111111111111111111111101//A>>>1
11111111111111111111111111111110//A>>2,负数:在左边补符号位1
111111111111111111111111111110// A>>>2
题目
给定两个32位的整数N与M,以及表示比特位置的i与j。编写一种方法,将M插入N,使得M从N的第j位开始,到第i位结束。假定从j位到i位足以容纳M,也即若M = 10 011,那么j和i之间至少可容纳5个位。例如,不可能出现j = 3和i = 2的情况,因为第3位和第2位之间放不下M。
输入:N = 10000000000, M = 10011, i = 2, j = 6
输出:N = 10001001100
输入: N = 0, M = 11111, i = 0, j = 4
输出:N = 11111
题目解析
题目大意是将 N 的 i 到 j 位用 M 代替(注意这里的 i 与 j 是从二进制的末尾开始的,并且是从 0 开始的),也就是说将 M 分成了三个数:0 — i-1(其余位为0), i — j(其余位为0), j+1 —最高位(其余位为0),这三个数字或运算的结果,就是最终答案。
- 0 — i-1(其余位为0):通过将 1 << i,然后减 1,最后和N进行与运算
例如 i = 2,
1 << i = 100(其余位为0)
(1 << i) - 1 = 11(其余位为0)
N & (1 << i) - 1 得到最后 i 由有 N 的前 0 — i - 1 位决定,其余位为0
- i — j(其余位为0): M << i 即可(其余位补0)
- j+1 —最高位(其余位为0):N >> j >> 1 << j << 1,即 N 右移 j + 1 位后再左移 j + 1 为,则 j + 1 —最高位保持不变,其余位为0(注意:java里面32位整数n左移32位的结果是n循环左移而不是置零,当j=31,会导致循环左移,则代码 1<<j+1应改为 1<<j<<1)
代码
class Solution {
public int insertBits(int N, int M, int i, int j) {
int left = N & (1 << i) - 1;
int right = N >> j >> 1 << j << 1;
int mid = M << i;
return left | mid | right;//( | 的顺序不影响结果)
}
}
示例
public class L0501 {
public static void main(String[] args) {
int N = 67, M = 15, i = 2, j = 5;
System.out.println(Integer.toBinaryString(N));
System.out.println(Integer.toBinaryString(M));
int l = N&(1<<i)-1;
int h = N>>j>>1<<j<<1;
int m = M<<i;
System.out.println(Integer.toBinaryString(l));
System.out.println(Integer.toBinaryString(h));
System.out.println(Integer.toBinaryString(m));
System.out.println(Integer.toBinaryString(l|h|m));
}
}
结果
1000011
1111
11
1000000
111100
1111111