每日一题--位运算之指定位替换(Google推荐面试书--Cracking the Coding Interview)

题目

  • 原文:
    You are given two 32-bit numbers, M and N, and two bit positions, i and j. Write a method to set all bits between i and j in M equal to N (e.g., N becomes a substring of M located at i and starting at j).
    EXAMPLE:
    Input: M = 10000000000, N = 10101, i = 2, j = 6
    Output: M = 10001010100
  • 译文:
    给定两个32位的数,M和N,还有两个指示位的数,i和j。 写程序使得M中第i位到第j的值与N中的相同(即:N变成M的位于第i位和第j位之间的子串)
    例子:
    输入: M = 10000000000, N = 10101, i = 2, j = 6
    输出: M = 10001010100

分析
解题思路为:使得M的[i,j]位为0,其他位不变i,然后与左移i位后的N做或运算。
其中,使得M的[i,j]位为0有两种方法:

  1. 构造一个第i位到第j位为0,其他位为1的数temp,与M按位与【代码见bit_substr1()】;
  2. 先保留M的[0,i)位到temp,再使M的[0,j]位为0(通过先右移再左移j+1位),然后与temp做或运算【代码见bit_substr2()】。

代码

#include<iostream>
#include<vector>
using namespace std;

void print_binary(int n) {
	vector<int> bitvec;
	int mask = 1;
	const int bit_len = 8;
	int len = bit_len * sizeof(int);
	while(len--) {
		if(n & mask) {
			bitvec.push_back(1);
		}
		else {
			bitvec.push_back(0);
		}
		mask <<= 1;
	}
	while(!bitvec.empty()) {
		cout << bitvec.back();
		bitvec.pop_back();
	}
	cout << endl;
}

void bit_substr1(int &m, int n, int i, int j) {
	//构造一个第i位到第j位为0,其他位为1的数temp
	int a = (1 << i) - 1; 
	int b = ~((1 << (j+1)) - 1);
	int temp = a | b;
	
	//将temp与m按位与,使得m的第i位到第j位为0,其他位不变 
	m = m & temp;
		
	//将m和左移i位后的n做或操作
	m = m | (n << i); 
}

void bit_substr2(int &m, int n, int i, int j) {
	//保留m中的[0,i)位到(其他位为0)temp
	int temp = m & ((1<<i) - 1);
	
	//使得m的[0,j]位为0,其他位不变 
	m = m >> (j+1);
	m = m << (j+1);
	
	//将m和左移i位后的n和temp做或操作 
	m = m | temp | (n << i);
}

int main() {
	int a = 1 << 10;
	cout << "    m is: ";
	print_binary(a); 
	int b = 21;
	cout << "    n is: ";
	print_binary(b);
	//bit_substr1(a, b, 2, 6); 
	bit_substr2(a, b, 2, 6);
	cout << "new m is: ";
	print_binary(a);
	  
	b = 15;
	cout << "new n is: ";
	print_binary(b);
	//bit_substr1(a, b, 4, 7);
	bit_substr2(a, b, 4, 7);
	cout << "now m is: ";
	print_binary(a); 
}

结果
在这里插入图片描述
位运算补充
有符号整型int和无符号整型unsigned int 右移对比:(前者正数补0负数补1,后者通通补0,左移两者都补0)

#include<iostream>
#import<cmath>
using namespace std;

int main() {
	//整型 
	int t =  -2;
	cout << "       -2 is:";
	print_binary(t);
	cout << "-2右移一位是:";
	print_binary(t >> 1);
	cout << "-2右移一位是:" << (t >> 1) << endl;
	//无符号整型
	unsigned int ut = pow(2,32) - 2;
	cout << "       " << ut << " is:";
	print_binary(ut);
	cout << ut << "右移一位是:";
	print_binary(ut >> 1);
	cout << ut << "右移一位是:" << (ut >> 1) << endl;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39860046/article/details/88073374
今日推荐