3.9 KiB
5.3. Flip Bit to Win
Hints: #358,#375,#390
You have an integer and you can flip exactly one bit from a 0 to a 1. Write code to find the length of the longest sequence of 1s you could create. Input: 1775, or 11011101111, Output: 8
Brute force idea: find all 0s, flip all of them, count all 1s sequences (how?), output max.
Another idea: find longest sequence of 1s as of now, flip adjacent 0 and count length, flip other 0 (if not end/beginning of sequence) and count length, output max.
But how to find first 0? and count consecutive 1s? And how to make it efficient?
Hint 1
Start with a brute force solution for each
Flipping function, need the position of the 0 bit.
boolean setBit(int num, int i) {
return num | (1 << i);
}
Length of the Longest Consecutive 1s in Binary Representation. Bit magic.
#include<bits/stdc++.h>
using namespace std;
int maxConsecutiveOnes(int num) {
// Initialize result
int count = 0;
// Count the number of iterations to reach num = 0.
while (num!=0) {
// This operation reduces length
// of every sequence of 1s by one.
num = (num & (num << 1));
count++;
}
return count;
}
11101111 (x)
& 11011110 (x << 1)
----------
11001110 (x & (x << 1))
^ ^
| |
trailing 1 removed
The operation x = (x & (x << 1)) reduces length of every sequence of 1s by one in binary representation of x. If we keep doing this operation in a loop, we end up with x = 0. The number of iterations required to reach 0 is the length of the longest consecutive sequence of 1s.
If I find all 0s, flip them, I can use this to find the longest sequence.
Number of leading zeros in binary representation of a given number.
#include <vector>
using namespace std;
bool findPosof0(int num) {
int i = sizeof(num) * 8; // number of bits in num
vector<int> positions;
while (i--) {
// checking if i th bit of num is 1
if (!(num & (1 << i))) {
positions.push_back(i);
}
num = (num << 1);
}
// found first 0
return positions;
}
int num = 17;
int max1s = 0;
// finds all positions of 0
vector<int> positions0 = findPosOf0(num);
for (pos : positions0) {
// flip the first 0, returns a boolean so don't know if this works
num = setBit(num, first0);
max1s = max(max1s, maxConsecutiveOnes(num));
}
// count consecutive 1s
cout << max1s << endl;
Time complexity O(2n) and space complexity O(2n).
Hint 2
Get Next: Picture a binary number-something with a bunch of 1s and Os spread out throughout the number. Suppose you flip a 1 to a 0 and a 0 to a 1. In what case will the number get bigger? In what case will it get smaller?
Flipping 1 to 0 makes it smaller, and vice versa.
Hint 3
If you flip a 1 to a 0 and a 0 to a 1, it will get bigger if the 0->1 bit is more significant than the 1->0 bit. How can you use this to create the next biggest number (with the same number of 1s)?
I don't know.
Hint 4
When you do a binary subtraction, you flip the rightmost 0s to a 1, stopping when you get to a 1 (which is also flipped). Everything (all the 1 s and 0s) on the left will stay put.
Yes. And in reverse, if we have a bunch of 11111s, if we add one, it will create many 0s.
Hint 5
Flipping a 0 to a 1 will create a bigger number. The farther right the index is the smaller the bigger number is. If we have a number like 1001, we want to flip the rightmost 0 (to create 1011). But if we have a number like 1010, we should not flip the rightmost 1.
Sure but we're not looking for the biggest , rather for the longest sequence of 1s. If we have 10111011, we should flip the second 0. In this case, flipping any 0 creates a sequence of two 1s. So it shouldn't matter 🤔.