5.3. flip bit to win done

This commit is contained in:
anebz 2020-03-25 23:41:45 +01:00
parent edaa0852ca
commit 6db72111bb
1 changed files with 30 additions and 15 deletions

View File

@ -1,7 +1,5 @@
# 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.
@ -94,32 +92,49 @@ for (pos : positions0) {
cout << max1s << endl;
```
Time complexity O(2n) and space complexity O(2n).
Time complexity O(2n) and space complexity O(2n) (n=\# bits)
## Hint 2
## Hints
> 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
> Flipping a O to a 1 can merge two sequences of 1s-but only if the two sequences are separated by only one 0
> 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)?
Exactly.
I don't know.
> Each sequence can be lengthened by merging it with an adjacent sequence (if any) or just flipping the immediate neighboring zero. You just need to find the best choice.
## Hint 4
So the two sequences of 1 separated by the one 0. In my algorithm I just find all 0s, flip and count, flip and count, and get the max. This takes O(n) time and O(n) space.
> 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.
> Try to do it in linear time, a single pass, and 0(1) space.
Yes. And in reverse, if we have a bunch of 11111s, if we add one, it will create many 0s.
I could if I had a string, but I guess I can't convert it to a string. I'd start counting all the 1s until finding a 0, keep a flag, count all 1s. When next 0 is found, flag=0, max1s=num, num=0, repeat. and then return max1s. But I don't know how to do that with logic operations.
## Hint 5
## Solution
> 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.
> [Brute force](https://github.com/careercup/CtCI-6th-Edition/blob/master/Java/Ch%2005.%20Bit%20Manipulation/Q5_03_Flip_Bit_to_Win/QuestionB.java)
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:.
Count all sequences of 1s and 0s, start from right to left and in each iteration either add one to the count of 1s, or add one to the count of 0s, or switch. How to switch? `int searchingFor = n & 1;` If n ends with 1, then searchingFor=1. if not, 0. Returns the rightest bit in the number. Then, move the number by n >>>= 1;
## Hint 6
* At the end of the function, we end up with [1, 2, 3, 3, 1]. Starting from right to left, there's one 0, then two 1s, then three 0s, etc.
* Then we search for the longest sequence. Iterate the sequence, get the \# zeros in the sequence and \# ones in left and right, if inside of bounds.
* If the amount of 0s is 1, then we can merge. And the sequence length is length of 1s to the left + 1 + length of 1s to the right.
* If there's more than one 0, add 1 to the longest sequence of 1s. 1110011, 3 > 2 --> 3 + 1 = 4. longest sequence of 1s would be of length 4.
* Update the maximum sequence length iteratively
* The end
>
This is kind of what I had thought of.
> [Optimal algorithm](https://github.com/careercup/CtCI-6th-Edition/blob/master/Java/Ch%2005.%20Bit%20Manipulation/Q5_03_Flip_Bit_to_Win/QuestionD.java)
O(b) time complexity, b=\#num_bits and **O(1) space**. To reduce the space usage, note that we don't need to hang on to the length of each sequence the entire
time. We only need it long enough to compare each 1s sequence to the immediately preceding 1s sequence.
We canjust walk through the integer doing this, tracking the current 1s sequence length and the previous 1s sequence length. When we see a 0, update previousLength (see code in link).
* If the next next bit is a 1 (by doing n & 2, or checking if the last 2 bits are 10 or 00), previousLength should be set to currentLength.
* If the next next bit is a 0, then we can't merge these sequences together. So, set previousLength to 0.
currentLength keeps track of the sequences of 1 without any unflipping. Each time we encounter a 0, we check for the next bit and update the previous and current lengths, O(1) space complexity.