Skip to content

Commit 39d1254

Browse files
committed
Bit Manipulation
1 parent 0650001 commit 39d1254

5 files changed

Lines changed: 267 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package chapter05BitManipulation;
2+
3+
/**
4+
*
5+
* Problem: Write a function to determine the number of bits you would need to
6+
* flip to convert integer A to integer B
7+
*
8+
* Example: Input 29(11101), 15(01111), Output: 2
9+
*
10+
*/
11+
public class Conversion {
12+
13+
// shift c repeatedly while checking the least significant bit
14+
public int count1(int a, int b) {
15+
int count = 0;
16+
int res = a ^ b;
17+
while (res != 0) {
18+
count += res & 1;
19+
res >>>= 1;
20+
}
21+
return count;
22+
}
23+
24+
// flip the least significant bit
25+
public int count2(int a, int b) {
26+
int count = 0;
27+
int res = a ^ b;
28+
while (res != 0) {
29+
count += res & 1;
30+
// clear the least significant in res 101000 & 100111 = 10000
31+
res = res & (res - 1);
32+
}
33+
return count;
34+
}
35+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package chapter05BitManipulation;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
*
8+
* Problem: Flip Bit to Win: You have an integer and you can flip exactly one
9+
* bit from a O to a 1. Write code to find the length of the longest sequence of
10+
* 1 s you could create.
11+
*
12+
* EXAMPLE Input: 1775 (or: 11011101111) Output: 8
13+
*
14+
*
15+
*/
16+
17+
public class FlipBitToWin {
18+
19+
/**
20+
* Method 1: Brute Force
21+
*
22+
* Time Complexity: O(b), where b is the length of the sequence
23+
*
24+
* Space COmplexity: O(b)
25+
*/
26+
public int longestSequence1(int n) {
27+
if (n == -1) {
28+
return Integer.BYTES * 8;
29+
}
30+
List<Integer> list = getSequence(n);
31+
return findLongestSequence(list);
32+
}
33+
34+
/**
35+
* return a list of the size of the sequence. The sequence starts off with
36+
* the number of 0s and then alternates with the counts of each value.
37+
*/
38+
private List<Integer> getSequence(int num) {
39+
List<Integer> list = new ArrayList<>();
40+
int iter = 0;
41+
int counter = 0;
42+
for (int i = 0; i < Integer.BYTES * 8; i++) {
43+
if ((num & 1) != iter) {
44+
list.add(counter);
45+
iter = iter == 0 ? 1 : 0; // flip 1 to 0, or 0 to 1
46+
counter = 0;
47+
}
48+
counter++;
49+
num >>>= 1;
50+
}
51+
list.add(counter);
52+
return list;
53+
}
54+
55+
private int findLongestSequence(List<Integer> list) {
56+
int max = 1;
57+
for (int i = 0; i < list.size(); i += 2) {
58+
int zerosSeq = list.get(i);
59+
int onesSeqRight = i - 1 >= 0 ? list.get(i - 1) : 0;
60+
int onesSeqLeft = i + 1 < list.size() ? list.get(i + 1) : 0;
61+
int thisSeq = 0;
62+
if (zerosSeq == 1) { // can merge
63+
thisSeq = onesSeqLeft + 1 + onesSeqRight;
64+
} else if (zerosSeq > 1) { // just ad a zero to either side
65+
thisSeq = 1 + Math.max(onesSeqLeft, onesSeqRight);
66+
} else if (zerosSeq == 0) { // no zero, but take either side
67+
thisSeq = Math.max(onesSeqRight, onesSeqRight);
68+
}
69+
max = Math.max(max, thisSeq);
70+
}
71+
return max;
72+
}
73+
74+
/**
75+
* Method 2:
76+
*
77+
* Walk through the integer, tracking the current 1s sequence length and the
78+
* previous 1s sequence length. When we meet a 0, update previousLength:
79+
*
80+
* 1. If the next bit is a 1, priviousLength should be set to current
81+
* length;
82+
*
83+
* 2. If the next bit is a 0, we cannot merge these sequences together. So,
84+
* set previousLength to 0;
85+
*
86+
* Time Complexity: O(b)
87+
*
88+
* Space Complexity: O(1)
89+
*
90+
*/
91+
public int longestSequence2(int num) {
92+
if (num == -1) {
93+
return Integer.BYTES;
94+
}
95+
int curLength = 0;
96+
int preLength = 0;
97+
int max = 1;
98+
while (num != 0) {
99+
if ((num & 1) == 1) { // current bit is a 1
100+
curLength++;
101+
} else if ((num & 1) == 0) { // current bit is a 0
102+
preLength = (num & 2) == 0 ? 0 : curLength;
103+
curLength = 0;
104+
}
105+
max = Math.max(max, preLength + 1 + curLength);
106+
num >>>= 1;
107+
}
108+
return max;
109+
}
110+
111+
public static void main(String[] args) {
112+
FlipBitToWin f = new FlipBitToWin();
113+
System.out.println(f.longestSequence1(1775));
114+
System.out.println(f.longestSequence2(1775));
115+
}
116+
}

src/chapter05BitManipulation/Intro.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,9 @@ public int updateBit(int num, int i, boolean bitIs1) {
6161
int mask = ~(1 << i);
6262
return (num & mask) | (val << i);
6363
}
64+
65+
// n == 0 | n is a power of 2
66+
public boolean powerOfTwo(int n) {
67+
return (n & (n - 1)) == 0;
68+
}
6469
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package chapter05BitManipulation;
2+
3+
/**
4+
* Problem: Given a positive integer, print the next smallest and the previous
5+
* largest number that have the same number of 1 bits in their binary
6+
* representation.
7+
*
8+
*
9+
*/
10+
11+
public class NextNumber {
12+
/**
13+
* 1. flip rightmost non-tailing zero, position p
14+
*
15+
* 2. clear bits to the right of p.
16+
*
17+
* 3. add in (c1 - 1) ones
18+
*
19+
* return the smallest number bigger than n with the same number ones.
20+
*/
21+
public int getNext(int num) {
22+
int c = num;
23+
// c0 is the number of zeros to the right of p
24+
// c1 is the number of ones to the right of p
25+
int c0 = 0;
26+
int c1 = 0;
27+
while ((c & 1) == 0 && c != 0) {
28+
c0++;
29+
c >>>= 1;
30+
}
31+
while ((c & 1) == 1) {
32+
c1++;
33+
c >>>= 1;
34+
}
35+
// 1100000. there is no bigger number with the same number of 1s
36+
if (c0 + c1 == 31 || c0 + c1 == 0) {
37+
return -1;
38+
}
39+
// rightmost non-trailing zero
40+
int p = c0 + c1;
41+
// 1. flip
42+
num |= (1 << p);
43+
// 2. clear bits to the right p
44+
int a = 1 << p;
45+
int b = a - 1;
46+
int mask = ~b;
47+
num = num & mask;
48+
// 3. add in (c1 - 1) ones
49+
a = 1 << (c1 - 1);
50+
b = a - 1;
51+
num |= b;
52+
return num;
53+
}
54+
55+
/**
56+
* 1. Initial Number
57+
*
58+
* 2. clear bits to the right of p.
59+
*
60+
* 3. insert c1 + 1 ones immediately to the right of the position of p
61+
*
62+
* return the smallest number bigger than n with the same number ones.
63+
*
64+
*/
65+
public int getPrev(int num) {
66+
int c = num;
67+
// c0 is the number of zeros to the right of p
68+
// c1 is the number of ones to the right of p
69+
int c0 = 0;
70+
int c1 = 0;
71+
while ((c & 1) == 1) {
72+
c1++;
73+
c >>>= 1;
74+
}
75+
// 111111
76+
if (c == 0) {
77+
return -1;
78+
}
79+
while ((c & 1) == 0 && (c != 0)) {
80+
c0++;
81+
c >>>= 1;
82+
}
83+
// rightmost non-trailing one
84+
int p = c0 + c1;
85+
// clear bits to the right of p
86+
// 2. clear bits to the right p
87+
int a = 1 << p;
88+
int b = a - 1;
89+
int mask = ~b;
90+
num = num & mask;
91+
// 3. insert c1 + 1 ones immediately to the right of the position of p
92+
int mask2 = (1 << (c1 + 1)) - 1;
93+
num |= mask2 << (c0 - 1);
94+
return num;
95+
}
96+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package chapter05BitManipulation;
2+
3+
/**
4+
*
5+
* Problem: Write a program to swap odd and even bits in an integer with as few
6+
* instructions as possible
7+
*
8+
*oxaa: 10101010
9+
*ox55: 01010101
10+
*/
11+
public class PairwiseSwap {
12+
public int swap(int num) {
13+
return (((num & 0xaaaaaaaa)) >>> 1) | ((num & 0x55555555) << 1);
14+
}
15+
}

0 commit comments

Comments
 (0)