
The last challenge of HackerRank's 30 Days of Code is about the bitwise AND operator. You can pass it with two nested loops, and many people do. But there is a neat observation that answers each test case in constant time, and working it out teaches you how to reason about bits instead of just trying every pair.
Bit tricks come up often in interviews, especially questions like "is this a power of two" or "what is the lowest set bit". This problem is a gentle way to build that thinking.
Problem
Take the set of numbers from 1 to N. Choose two different numbers A and B from it, with A < B. Among all such pairs, find the largest value of A & B (bitwise AND) that is strictly less than a given K.
Input format: the first line has T, the number of test cases. Each of the next T lines has two integers, N and K.
Output format: for each test case, print the answer on its own line.
Constraints: 1 <= T <= 10^3, 2 <= N <= 10^3, 2 <= K <= N.
Input
3
5 2
8 5
2 2
Output
1
4
0
For N = 5 and K = 2, the possible AND values are 0, 1, 2 and 4. The only ones below 2 are 0 and 1, so the answer is 1.
Approach
The simple way. Try every pair, compute A & B, and keep the largest that is below K. With N = 1000 that is about 500,000 pairs per test, and with 1000 tests about 5 x 10^8 operations. It passes on HackerRank, but only just, and it does not teach much.
The better way. The best we can hope for is K - 1. So ask: is there a pair whose AND is exactly K - 1?
- Let
a = K - 1. If we useaitself asA, we need a largerBthat contains every 1-bit ofa. Thena & Bequalsa. - The smallest number larger than
athat contains all its bits isa | (a + 1). Adding 1 flips the lowest 0-bit ofato 1, and OR-ing keeps everything else. Sincea + 1 = K, this is(K - 1) | K. - If
(K - 1) | K <= N, thatBexists in the set and the answer isK - 1. - Otherwise the answer is
K - 2.
Why is K - 2 always possible in the second case? If K - 1 were even, its lowest bit would be 0, and (K - 1) | K would just be K, which is at most N. So the second case only happens when K - 1 is odd. Then K - 2 is even, and (K - 2) & (K - 1) = K - 2, with both numbers inside the set.
Dry run. N = 8, K = 5: a = 4 (100 in binary), 4 | 5 = 5 (101), and 5 <= 8, so the answer is 4. N = 5, K = 2: a = 1, 1 | 2 = 3, and 3 <= 5, so the answer is 1. N = 2, K = 2: 1 | 2 = 3 is more than 2, so the answer is K - 2 = 0.
Solution in Java
The older code on this page used the double loop. It was correct, but it started A at 0, which is not in the set (harmless, since anything AND 0 is 0), and it did roughly half a billion operations in the worst case. The version below is O(1) per test.
import java.util.Scanner;
public class Solution {
// Largest A & B (1 <= A < B <= n) that is strictly less than k.
static int maxAnd(int n, int k) {
int a = k - 1; // the best value we could hope for
// a & B == a needs a B > a that contains every 1-bit of a.
// The smallest such B is a | (a + 1), and a + 1 is just k.
if ((a | k) <= n) {
return a;
}
return k - 2; // always reachable when the check above fails
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
StringBuilder out = new StringBuilder();
while (t-- > 0) {
int n = sc.nextInt();
int k = sc.nextInt();
out.append(maxAnd(n, k)).append('\n');
}
System.out.print(out);
}
}
Because a formula is easy to get subtly wrong, I checked it against the brute-force double loop for every N from 2 to 300 and every valid K. There were no mismatches. A few extra cases: 1000 1000 gives 998, 7 4 gives 3 (3 AND 7), and 6 6 gives 4 (4 AND 5).
Output
1
4
0
Complexity
Time: O(1) per test case, so O(T) overall. The brute force is O(N^2) per test.
Space: O(1).
Common mistakes
- Using
&&instead of&.&&is logical AND on booleans and will not compile with ints in Java.&works bit by bit. - Forgetting operator precedence. In Java,
a | k <= nis read asa | (k <= n)and fails to compile. Always bracket bitwise expressions:(a | k) <= n. - Allowing A equal to B.
A & Ais justA, which would make the problem trivial and wrong. The two numbers must be different. - Using
<=K. The answer must be strictly less than K.
Related: Day 10: Binary Numbers is a good warm-up on binary, and Day 28: RegEx, Patterns, and Intro to Databases is the previous day.
Tip: try to solve the problem yourself before reading the solution. Use the code as a reference to check your approach, and make sure you understand why it works.
More HackerRank solutions All coding problems MCQ practice
See everything in one place: Coding Problems and Solutions
Comments
Post a Comment