5.3. flip bit to win v1
This commit is contained in:
parent
58d12aa256
commit
edaa0852ca
|
|
@ -0,0 +1,125 @@
|
|||
# 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.
|
||||
|
||||
```c++
|
||||
boolean setBit(int num, int i) {
|
||||
return num | (1 << i);
|
||||
}
|
||||
```
|
||||
|
||||
[Length of the Longest Consecutive 1s in Binary Representation](https://www.geeksforgeeks.org/length-longest-consecutive-1s-binary-representation/). Bit magic.
|
||||
|
||||
```c++
|
||||
#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;
|
||||
}
|
||||
```
|
||||
|
||||
```c++
|
||||
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](https://www.geeksforgeeks.org/number-of-leading-zeros-in-binary-representation-of-a-given-number/).
|
||||
|
||||
```c++
|
||||
#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 :thinking:.
|
||||
|
||||
## Hint 6
|
||||
|
||||
>
|
||||
Loading…
Reference in New Issue