1+ package com .ctci .bitmanipulation ;
2+
3+ /**
4+ * @author rampatra
5+ * @since 2019-03-17
6+ */
7+ public class NextNumber {
8+
9+ private static class NextLargerAndSmallerNumber {
10+ int nextLarger ;
11+ int nextSmaller ;
12+ }
13+
14+ /**
15+ * Given a positive integer, print the next smallest and the next largest number that have the same number of
16+ * 1 bits in their binary representation.
17+ *
18+ * @param n a positive integer.
19+ * @return an object containing the next larger and next smaller number containing the identical set bits.
20+ */
21+ private static NextLargerAndSmallerNumber getNextLargerAndSmallerNumber (int n ) {
22+ NextLargerAndSmallerNumber result = new NextLargerAndSmallerNumber ();
23+ result .nextLarger = getNextLarger (n );
24+ result .nextSmaller = getNextSmaller (n );
25+ return result ;
26+ }
27+
28+ private static int getNextLarger (int n ) {
29+ int zeroPrecededByOneFromRight = 0 ;
30+ int noOfOnes = 0 ;
31+ int mask = 1 ;
32+
33+ /* Find the position of the bit pattern '01' from the right and then make it '10'.
34+ For example, see below:
35+
36+ n = 10110110011110
37+ ^^
38+ n = 10110110101110 (after bit swap)
39+ */
40+ for (int i = 0 ; i < Integer .BYTES * 8 - 1 ; i ++) {
41+ if ((n & mask ) == mask ) {
42+ if ((n & mask << 1 ) == 0 ) {
43+ n = (n & ~mask ) | mask << 1 ; // swap the bits
44+ break ;
45+ }
46+ noOfOnes ++;
47+ }
48+ zeroPrecededByOneFromRight ++;
49+ mask <<= 1 ;
50+ }
51+
52+ if (zeroPrecededByOneFromRight == Integer .BYTES * 8 - 1 ) {
53+ return -1 ;
54+ }
55+
56+ /* Shift all the 1s to the right end and then fill with 0s until the bit pattern '01.
57+ For example, consider the above number:
58+
59+ n = 10110110101110 (after bit swap)
60+ ^^
61+ next larger = 10110110100111 (the 1s are shifted to the right end)
62+ */
63+ mask = 1 ;
64+ for (int i = 0 ; i < zeroPrecededByOneFromRight ; i ++) {
65+ if (i < noOfOnes ) {
66+ n = n | mask ; // set the bits
67+ } else {
68+ n = n & ~mask ; // unset the bits
69+ }
70+ mask <<= 1 ;
71+ }
72+ return n ;
73+ }
74+
75+ private static int getNextSmaller (int n ) {
76+ int onePrecededByZeroFromRight = 0 ;
77+ int noOfZeros = 0 ;
78+ int mask = 1 ;
79+
80+ // find the position of the bit pattern '10' from the right and then make it '01'
81+ for (int i = 0 ; i < Integer .BYTES * 8 - 1 ; i ++) {
82+ if ((n & mask ) == 0 ) {
83+ if ((n & mask << 1 ) == mask << 1 ) {
84+ n = (n | mask ) & ~(mask << 1 ); // swap the bits
85+ break ;
86+ }
87+ noOfZeros ++;
88+ }
89+ onePrecededByZeroFromRight ++;
90+ mask <<= 1 ;
91+ }
92+
93+ if (onePrecededByZeroFromRight == Integer .BYTES * 8 - 1 ) {
94+ return -1 ;
95+ }
96+
97+ // shift all the 0s to the right end and then fill with 1s until the bit pattern '10'
98+ mask = 1 ;
99+ for (int i = 0 ; i < onePrecededByZeroFromRight ; i ++) {
100+ if (i < noOfZeros ) {
101+ n = n & ~mask ; // unset the bits
102+ } else {
103+ n = n | mask ; // set the bits
104+ }
105+ mask <<= 1 ;
106+ }
107+ return n ;
108+ }
109+
110+ public static void main (String [] args ) {
111+ NextLargerAndSmallerNumber of0 = getNextLargerAndSmallerNumber (0 );
112+ System .out .println ("Next larger of 0: " + of0 .nextLarger );
113+ System .out .println ("Next smaller of 0: " + of0 .nextSmaller );
114+
115+ NextLargerAndSmallerNumber of2 = getNextLargerAndSmallerNumber (2 );
116+ System .out .println ("Next larger of 2: " + of2 .nextLarger );
117+ System .out .println ("Next smaller of 2: " + of2 .nextSmaller );
118+
119+ NextLargerAndSmallerNumber of5 = getNextLargerAndSmallerNumber (5 );
120+ System .out .println ("Next larger of 5: " + of5 .nextLarger );
121+ System .out .println ("Next smaller of 5: " + of5 .nextSmaller );
122+
123+ NextLargerAndSmallerNumber of7 = getNextLargerAndSmallerNumber (7 );
124+ System .out .println ("Next larger of 7: " + of7 .nextLarger );
125+ System .out .println ("Next smaller of 7: " + of7 .nextSmaller );
126+
127+ NextLargerAndSmallerNumber of8 = getNextLargerAndSmallerNumber (8 );
128+ System .out .println ("Next larger of 8: " + of8 .nextLarger );
129+ System .out .println ("Next smaller of 8: " + of8 .nextSmaller );
130+
131+ NextLargerAndSmallerNumber of15 = getNextLargerAndSmallerNumber (15 );
132+ System .out .println ("Next larger of 15: " + of15 .nextLarger );
133+ System .out .println ("Next smaller of 15: " + of15 .nextSmaller );
134+ }
135+ }
0 commit comments