WIKI

Bit manipulation is the act of algorithmically manipulating bits or other pieces of data shorter than a word. Computer programming tasks that require bit manipulation include low-level device control, error detection and correction algorithms, data compression, encryption algorithms, and optimization. For most other tasks, modern programming languages allow the programmer to work directly with abstractions instead of bits that represent those abstractions. Source code that does bit manipulation makes use of the bitwise operations: AND, OR, XOR, NOT, and bit shifts.

Bit manipulation, in some cases, can obviate or reduce the need to loop over a data structure and can give many-fold speed ups, as bit manipulations are processed in parallel, but the code can become more difficult to write and maintain.

DETAILS

Basics

At the heart of bit manipulation are the bit-wise operators & (and), | (or), ~ (not) and ^ (exclusive-or, xor) and shift operators a << b and a >> b.

There is no boolean operator counterpart to bitwise exclusive-or, but there is a simple explanation. The exclusive-or operation takes two inputs and returns a 1 if either one or the other of the inputs is a 1, but not if both are. That is, if both inputs are 1 or both inputs are 0, it returns 0. Bitwise exclusive-or, with the operator of a caret, ^, performs the exclusive-or operation on each pair of bits. Exclusive-or is commonly abbreviated XOR.

  • Set union A | B
  • Set intersection A & B
  • Set subtraction A & ~B
  • Set negation ALL_BITS ^ A or ~A
  • Set bit A |= 1 << bit
  • Clear bit A &= ~(1 << bit)
  • Test bit (A & 1 << bit) != 0
  • Extract last bit A&-A or A&~(A-1) or x^(x&(x-1))
  • Remove last bit A&(A-1)
  • Get all 1-bits ~0

Examples

Count the number of ones in the binary representation of the given number

int count_one(int n) {

while(n) {

n = n&(n-1);

count++;

}

return count;

}

Is power of four (actually map-checking, iterative and recursive methods can do the same)

bool isPowerOfFour(int n) {

return !(n&(n-1)) && (n&0x55555555);

//check the 1-bit location;

}

^ tricks

Use ^ to remove even exactly same numbers and save the odd, or save the distinct bits and remove the same.

SUM OF TWO INTEGERS

Use ^ and & to add two integers

int getSum(int a, int b) {

return b==0? a:getSum(a^b, (a&b)<<1); //be careful about the terminating condition;

}

MISSING NUMBER

Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. For example, Given nums = [0, 1, 3] return 2. (Of course, you can do this by math.)

int missingNumber(vector<int>& nums) {

int ret = 0;

for(int i = 0; i < nums.size(); ++i) {

ret ^= i;

ret ^= nums[i];

}

return ret^=nums.size();

}

| tricks

Keep as many 1-bits as possible

Find the largest power of 2 (most significant bit in binary form), which is less than or equal to the given number N.

long largest_power(long N) {

//changing all right side bits to 1.

N = N | (N>>1);

N = N | (N>>2);

N = N | (N>>4);

N = N | (N>>8);

N = N | (N>>16);

return (N+1)>>1;

}

REVERSE BITS

Reverse bits of a given 32 bits unsigned integer.

Solution

uint32_t reverseBits(uint32_t n) {

unsigned int mask = 1<<31, res = 0;

for(int i = 0; i < 32; ++i) {

if(n & 1) res |= mask;

mask >>= 1;

n >>= 1;

}

return res;

}

uint32_t reverseBits(uint32_t n) {

uint32_t mask = 1, ret = 0;

for(int i = 0; i < 32; ++i){

ret <<= 1;

if(mask & n) ret |= 1;

mask <<= 1;

}

return ret;

}

& tricks

Just selecting certain bits

Reversing the bits in integer

x = ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1);

x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2);

x = ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4);

x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);

x = ((x & 0xffff0000) >> 16) | ((x & 0x0000ffff) << 16);

BITWISE AND OF NUMBERS RANGE

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. For example, given the range [5, 7], you should return 4.

Solution

int rangeBitwiseAnd(int m, int n) {

int a = 0;

while(m != n) {

m >>= 1;

n >>= 1;

a++;

}

return m<<a;

}

NUMBER OF 1 BITS

Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).

Solution

int hammingWeight(uint32_t n) {

int count = 0;

while(n) {

n = n&(n-1);

count++;

}

return count;

}

int hammingWeight(uint32_t n) {

ulong mask = 1;

int count = 0;

for(int i = 0; i < 32; ++i){ //31 will not do, delicate;

if(mask & n) count++;

mask <<= 1;

}

return count;

}

Application

REPEATED DNA SEQUENCES

All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
For example,
Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",
Return: ["AAAAACCCCC", "CCCCCAAAAA"].

Solution

class Solution {

public:

vector<string> findRepeatedDnaSequences(string s) {

int sLen = s.length();

vector<string> v;

if(sLen < 11) return v;

char keyMap[1<<21]{0};

int hashKey = 0;

for(int i = 0; i < 9; ++i) hashKey = (hashKey<<2) | (s[i]-'A'+1)%5;

for(int i = 9; i < sLen; ++i) {

if(keyMap[hashKey = ((hashKey<<2)|(s[i]-'A'+1)%5)&0xfffff]++ == 1)

v.push_back(s.substr(i-9, 10));

}

return v;

}

};

But the above solution can be invalid when repeated sequence appears too many times, in which case we should use unordered_map<int, int> keyMap to replace char keyMap[1<<21]{0}here.

MAJORITY ELEMENT

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. (bit-counting as a usual way, but here we actually also can adopt sorting and Moore Voting Algorithm)

Solution

int majorityElement(vector<int>& nums) {

int len = sizeof(int)*8, size = nums.size();

int count = 0, mask = 1, ret = 0;

for(int i = 0; i < len; ++i) {

count = 0;

for(int j = 0; j < size; ++j)

if(mask & nums[j]) count++;

if(count > size/2) ret |= mask;

mask <<= 1;

}

return ret;

}

SINGLE NUMBER III

Given an array of integers, every element appears three times except for one. Find that single one. (Still this type can be solved by bit-counting easily.) But we are going to solve it by digital logic design

Solution

//inspired by logical circuit design and boolean algebra;

//counter - unit of 3;

//current   incoming  next

//a b            c    a b

//0 0            0    0 0

//0 1            0    0 1

//1 0            0    1 0

//0 0            1    0 1

//0 1            1    1 0

//1 0            1    0 0

//a = a&~b&~c + ~a&b&c;

//b = ~a&b&~c + ~a&~b&c;

//return a|b since the single number can appear once or twice;

int singleNumber(vector<int>& nums) {

int t = 0, a = 0, b = 0;

for(int i = 0; i < nums.size(); ++i) {

t = (a&~b&~nums[i]) | (~a&b&nums[i]);

b = (~a&b&~nums[i]) | (~a&~b&nums[i]);

a = t;

}

return a | b;

}

;

MAXIMUM PRODUCT OF WORD LENGTHS

Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.

Example 1:
Given ["abcw", "baz", "foo", "bar", "xtfn", "abcdef"]
Return 16
The two words can be "abcw", "xtfn".

Example 2:
Given ["a", "ab", "abc", "d", "cd", "bcd", "abcd"]
Return 4
The two words can be "ab", "cd".

Example 3:
Given ["a", "aa", "aaa", "aaaa"]
Return 0
No such pair of words.

Solution

Since we are going to use the length of the word very frequently and we are to compare the letters of two words checking whether they have some letters in common:

  • using an array of int to pre-store the length of each word reducing the frequently measuring process;
  • since int has 4 bytes, a 32-bit type, and there are only 26 different letters, so we can just use one bit to indicate the existence of the letter in a word.

int maxProduct(vector<string>& words) {

vector<int> mask(words.size());

vector<int> lens(words.size());

for(int i = 0; i < words.size(); ++i) lens[i] = words[i].length();

int result = 0;

for (int i=0; i<words.size(); ++i) {

for (char c : words[i])

mask[i] |= 1 << (c - 'a');

for (int j=0; j<i; ++j)

if (!(mask[i] & mask[j]))

result = max(result, lens[i]*lens[j]);

}

return result;

}

Attention

  • result after shifting left(or right) too much is undefined
  • right shifting operations on negative values are undefined
  • right operand in shifting should be non-negative, otherwise the result is undefined
  • The & and | operators have lower precedence than comparison operators

SETS

All the subsets
A big advantage of bit manipulation is that it is trivial to iterate over all the subsets of an N-element set: every N-bit value represents some subset. Even better, if A is a subset of B then the number representing A is less than that representing B, which is convenient for some dynamic programming solutions.

It is also possible to iterate over all the subsets of a particular subset (represented by a bit pattern), provided that you don’t mind visiting them in reverse order (if this is problematic, put them in a list as they’re generated, then walk the list backwards). The trick is similar to that for finding the lowest bit in a number. If we subtract 1 from a subset, then the lowest set element is cleared, and every lower element is set. However, we only want to set those lower elements that are in the superset. So the iteration step is just i = (i - 1) & superset.

vector<vector<int>> subsets(vector<int>& nums) {

vector<vector<int>> vv;

int size = nums.size();

if(size == 0) return vv;

int num = 1 << size;

vv.resize(num);

for(int i = 0; i < num; ++i) {

for(int j = 0; j < size; ++j)

if((1<<j) & i) vv[i].push_back(nums[j]);

}

return vv;

}

Actually there are two more methods to handle this using recursion and iteration respectively.

BITSET

A bitset stores bits (elements with only two possible values: 0 or 1, true or false, ...).
The class emulates an array of bool elements, but optimized for space allocation: generally, each element occupies only one bit (which, on most systems, is eight times less than the smallest elemental type: char).

// bitset::count

#include <iostream>       // std::cout

#include <string>         // std::string

#include <bitset>         // std::bitset

int main () {

std::bitset<8> foo (std::string("10110011"));

std::cout << foo << " has ";

std::cout << foo.count() << " ones and ";

std::cout << (foo.size()-foo.count()) << " zeros.\n";

return 0;

}

Always welcom new ideas and practical tricks, just leave them in the comments!

bit manipulation的更多相关文章

  1. backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized.

    昨天在检查YourSQLDba备份时,发现有台数据库做备份时出现了下面错误信息,如下所示: <Exec>   <ctx>yMaint.ShrinkLog</ctx> ...

  2. Hololens开发笔记之Gesture手势识别(Manipulation手势控制物体旋转)

    Manipulation gesture:保持点击手势,在3D世界中绝对运动 当你想要全息图像1:1响应用户手部移动时,操纵手势能被用于移动.缩放或旋转全息图像.如此的一个用处是使得用户可以在世界中绘 ...

  3. Hololens开发笔记之Gesture手势识别(Manipulation手势控制物体平移)

    Manipulation gesture:保持点击手势,在3D世界中绝对运动 当你想要全息图像1:1响应用户手部移动时,操纵手势能被用于移动.缩放或旋转全息图像.如此的一个用处是使得用户可以在世界中绘 ...

  4. Track files and folders manipulation in Windows

    The scenario is about Business Secret and our client do worry about data leakage. They want to know ...

  5. Data manipulation primitives in R and Python

    Data manipulation primitives in R and Python Both R and Python are incredibly good tools to manipula ...

  6. VK Cup 2012 Qualification Round 2 C. String Manipulation 1.0 字符串模拟

    C. String Manipulation 1.0 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 codeforces.com/problemset/pr ...

  7. Bash String Manipulation Examples – Length, Substring, Find and Replace--reference

    In bash shell, when you use a dollar sign followed by a variable name, shell expands the variable wi ...

  8. windows phone 之手势识别(Manipulation)

    在Windows Phone 7的多触摸屏上可以检测到至少四根同时存在的手指,并且一起操作使触摸屏充分发挥效果. 在silverlight开发中通过事件来实现触屏事件的检测,包括低级别的和高级别的接口 ...

  9. WPF Multi-Touch 开发:高级触屏操作(Manipulation)

    原文 WPF Multi-Touch 开发:高级触屏操作(Manipulation) 在上一篇中我们对基础触控操作有了初步了解,本篇将继续介绍触碰控制的高级操作(Manipulation),在高级操作 ...

  10. Best packages for data manipulation in R

    dplyr and data.table are amazing packages that make data manipulation in R fun. Both packages have t ...

随机推荐

  1. 数据库SQL server 删除一张表中的重复记录

    --建立一张表 create table cat( catId int, catName varchar(40) ) --将下边的插入语句,多执行几次. insert into catvalues(1 ...

  2. Docker - Image创建

    自己创建Image会有一些好处,可以选择最新的版本,而且从国内的镜像创建时更新软件也会从该镜像获取,速度更快. (1)安装debootstrap zhouh1@uhome:/media/zhouh1/ ...

  3. 回顾Spring MVC_01_概述_入门案例

    SpringMVC: SpringMVC是Spring为展现层提供的基于MVC设计的优秀的Web框架,是目前最主流的MVC框架之一 SpringMVC通过注解,让POJO成为处理请求的控制器,而无须实 ...

  4. Android(java)学习笔记162:开发一个多界面的应用程序之两种意图

    1.两种意图: (1)显式意图: 在代码里面用intent设置要开启Activity的字节码.class文件: (2)隐式意图: Android(java)学习笔记218:开发一个多界面的应用程序之人 ...

  5. linux ABORT的应用详解

    NAME ABORT - 退出当前事务 SYNOPSIS ABORT [ WORK | TRANSACTION ] DESCRIPTION 描述 ABORT 回卷当前事务并且废弃所有当前事务中做的更新 ...

  6. 递推(三):POJ中的三道递推例题POJ 1664、POJ 2247和POJ 1338

    [例9]放苹果(POJ 1664) Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. In ...

  7. day13 函数模块之序列化 random 模块 os模块 sys模块 hashlib模块 collections模块

    json import json dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串 ...

  8. luogu 5月月赛 #A

    T29693 取石子 题目描述 Alice 和 Bob 在玩游戏 他们有 n 堆石子,第 i 堆石子有ai​ 个,保证初始时 ai​≤ai+1​(1≤i<n) . 现在他们轮流对这些石子进行操作 ...

  9. HDU1116(欧拉路径+并查集)

    题意: 给出一些字符串,有这两个字符串,如果第一个字符串的最后一个字母和第二个字符串的第一个字母是一样的,则这两个字符串是可以连接在一起的. 问给出的这些字符串能否串成一个环或者一整个链. 思路: 将 ...

  10. selenium——操作滚动条

    在自动化测试的过程中,难免会应用到翻页键,但是webdriver提供的方法都是操作当前页面可见的元素,对于未在当前范围展示的翻页键,该如何操作呢? 小编在这里介绍一种方法:使用JavaScript操作 ...