A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N.
For example, number 9 has binary representation 1001 and contains a binary gap of length 2. The number 529 has binary representation 1000010001 and contains two binary gaps: one of length 4 and one of length 3. The number 20 has binary representation 10100 and contains one binary gap of length 1. The number 15 has binary representation 1111 and has no binary gaps.
Write a function:
int solution(int N); that, given a positive integer N, returns the length of its longest binary gap. The function should return 0 if N doesn't contain a binary gap.
For example, given N = 1041 the function should return 5, because N has binary representation 10000010001 and so its longest binary gap is of length 5.
public int solution(int n) {
// write your code in Java SE 8
String binaryRep = Integer.toBinaryString(n);
System.out.println("Binary Representation of " + n + " = " + binaryRep);
List<String> strList = new ArrayList<String>();
int count = 0;
for (int i = 0; i < binaryRep.length(); i++) { // Loop through the each number
String str = binaryRep.charAt(i) + ""; // getting one by one number
if(str.equals("0")){
for(int j = i;j<binaryRep.length();j++){ //Get each next element
String str1 = binaryRep.charAt(j) + "";
if(!str.equals("1") && str.equals(str1)){
if(!strList.isEmpty() && count >= strList.size()){
strList.add(str1);
}else if(strList.isEmpty()){
strList.add(str1);
}
count ++;
}else{
count = 0;
break;
}
}
}
}
return strList.size();
}
I haven't tested your code yet, but it seems very inefficient if your goal is just counting the longest 'binary gap'.
Problems in your code:
- Makes
java.lang.String
when it can be justchar
. Making objects is much slower than making primitive types. - Makes a list when it's able to simply count. As long as you're only going to need size of the list, you can just count it in a integer variable.
- Stupid algorithm. A substring of a string can't be longer than the original one. I'm talking about the second
for
loop. For example, let's say you're counting binary gap of1001
. Then your algorithm counts binary gap of001
and then01
. You don't need to count the second one at all. And it's happening becuase you have two for loops.
The biggest problem is, that it's possible to solve this problem without converting int
into java.lang.String
at all. And in case you got this problem from a textbook, I believe this is the 'correct' answer: To use bitwise operators.
public static int solution(int num) {
int ptr; //Used for bitwise operation.
for(ptr=1; ptr>0; ptr<<=1) //Find the lowest bit 1
if((num&ptr) != 0)
break;
int cnt=0; //Count the (possible) gap
int ret=0; //Keep the longest gap.
for(; ptr>0; ptr<<=1) {
if((num&ptr) != 0) { //If it's bit 1
ret = cnt < ret ? ret : cnt; //Get the bigger one between cnt and ret
cnt=-1; //Exclude this bit
}
cnt++; //Increment the count. If this bit is 1, then cnt would become 0 beause we set the cnt as -1 instead of 0.
}
return ret;
}
There is no need to place the contents of the binary string into an Array (unless of course this is a requirement), simply iterate through the string itself and use the String.substring() method to retrieve the string represented value of each binary digit, as in:
String digit = binaryString.substring(i, i+1);
It all boils down to counting the number of 0's between any set of 1's and keeping track of those 0's by using a Integer data type variable that is incremented every time a 0 is encountered. This same variable is reset to 0 every time a 1 is encountered but before it's reset you would compare it to yet another predefined Integer variable which would hold the longest run of 0's encountered, for example:
if(binaryString.substring(i, i+1).equals("1")) {
if (zeroHit > longest) { longest = zeroHit; }
zeroHit = 0;
}
else { zeroHit++; }
The whole method might look something like this:
private static int solution(int intValue) {
String binaryString = Integer.toBinaryString(intValue);
int zeroHit = 0;
int longest = 0;
for (int i = 0; i < binaryString.length(); i++) {
if(binaryString.substring(i, i+1).equals("1")) {
if (zeroHit > longest) { longest = zeroHit; }
zeroHit = 0;
}
else { zeroHit++; }
}
return longest;
}
Here is my modest solution. Now I see that it's looks like modification of DevilsHnd answer. I tested it
public int countZeros(int n) {
String binaryRep = Integer.toBinaryString(n);
char[] nChars = binaryRep.toCharArray();
int nElemLength = Math.min(binaryRep.lastIndexOf('1') + 1, nChars.length);
if (nElemLength <= 2) {
return 0;
}
String[] elementsParts = binaryRep.substring(0, nElemLength).split("1");
int zeroLength = 0;
for (String elementsPart : elementsParts) {
if (elementsPart.length() > zeroLength) {
zeroLength = elementsPart.length();
}
}
return zeroLength;
}
What about this algorithm. Is it bad for time performance or good?
int count = 0, prevCount = 0;
while (a > 1) {
if (a % 2 == 0) {
count++;
if (count > prevCount)
prevCount++;
} else {
count = 0;
}
a = a/2;
}
if(a % 2 == 0)
prevCount++;
I think your code is a little bit confusing,check this one.
public int solution(int n) {
if (n <= 0) return 0;
char[] chars = Integer.toBinaryString(n).toCharArray();
ArrayList<Integer> arrayList = new ArrayList<>();
int maxCount = 0;
for (int i = 0; i < chars.length; i++) {
while (chars[i] == '0' && i + 1 < chars.length) {
maxCount++;
i++;
if (i + 1 == chars.length && chars[i] == '0')
maxCount = 0;
}
if (maxCount != 0)
arrayList.add(maxCount);
maxCount = 0;
}
return arrayList.isEmpty() ? 0 : Collections.max(arrayList);
}
Hi this is my solution for this task. I had Task Score : 100% Correctness : 100%
public int solution(int N) {
String binary = Integer.toBinaryString(N);
int[] table = new int[binary.length()];
for (int i=0;i<binary.length();i++){
int number = Integer.parseInt(binary.substring(i,i+1));
table[i] = number;
}
int resu = 0;
int res = 0;
for (int i=0;i<table.length;i++){
if (table[i] == 1){
if (resu > res){
res = resu;
}
resu = 0;
}else {
resu++;
}
}
return res;
}
For the benefit of all, here is my solution to the Binary Gap which got me 100% for both Task Score and Task Correctness:
class Solution {
public int solution(int N) {
String nStr = Integer.toBinaryString(N);
boolean isCounting = false;
int j=0;
int[] seqs = new int[32];
for (int i=0; i<nStr.length(); i++)
{
if ( nStr.charAt(i) == '1')
{
if (!isCounting)
{
isCounting = true;
seqs[j] = 0;
}
else // isCounting, turn it off
{
isCounting = false;
j++;
}
}
else // nStr.charAt(i) == '0'
{
if (!isCounting)
isCounting = true;
seqs[j]++;
}
}
if (isCounting == true)
seqs[j] = 0;
int maxGap = 0;
for (int k=0; k<seqs.length; k++)
if (seqs[k] > maxGap)
maxGap = seqs[k];
return maxGap;
}
}
OBJECTIVE-C SOLUTION O(2n)
Results given by Codility
Task Score: 100%
Correctness: 100%
Performance: Not assesed
Time Complexity
The worst case time complexity is O(2n)
Algorithm Explanation
FACTS
Every valid gap starts with a '1' and close with another '1', with at least one 'zero' between them.
- 1001 - Is a valid gap
- 00100 - Isn't a valid gap
- 10100 - Is a valid gap
- 11111 - Isn't a valid gap
STEP 1
- Get the bits of n, using an auxiliary method wich has O(n) Complexity
STEP 2
- Iterate over each bit we got in Step One
- Start looking for the first '1' - since our flag 'hasStartPattern' is false in the first iteration, we'll look for the first occurrence of '1', that means we have a valid start pattern and we change the flag 'hasStartPattern' to true for the next iterations we should validate if the current bit is '0' and use a counter, in this case 'candidates'.
- Only if, there is another '1' in the incoming bits, we are sure that we have a valid binary gap, then we compare our previous 'candidates' with our current 'gapCounter' in order to keep the highest one.
- In case that there isn't another '1' to close the gap, we never change the value of 'gapCounter' and we return 0.
+(int)solutionTwo:(int)n {
// STEP 1
// O(n)
NSString *bits = [self getBitsForNumber:n];
BOOL hasStartPattern = NO;
int candidates = 0;
int gapCounter = 0;
// STEP 2
// O(n)
for (int i=0; i < bits.length; i++) {
char currentBit = [bits characterAtIndex:i];
if ( hasStartPattern && currentBit == '0' ) {
candidates++;
}
else if ( hasStartPattern && currentBit == '1' ) {
// At least one '1' exist as a close pattern
if (candidates > gapCounter) {
gapCounter = candidates;
}
candidates = 0;
}
else if (currentBit == '1') {
hasStartPattern = YES; // At least one '1' exist as an open pattern
}
}
return gapCounter;
}
/*
Time Complexity:
- The worst case time complexity for this auxiliary method is O(n)
*/
+(NSString*)getBitsForNumber:(int)n {
NSMutableString *bits = [NSMutableString string];
while(n) {
[bits insertString:((n&1)? @"1" : @"0") atIndex:0];
n /= 2;
}
return bits;
}
OBJECTIVE-C SOLUTION O(n)
Results given by Codility
Task Score: 100%
Correctness: 100%
Performance: Not assesed
Time Complexity
The worst case time complexity is O(n)
Algorithm Explanation
FACTS
Every valid gap starts with a '1' and close with another '1', with at least one 'zero' between them.
- 1001 - Is a valid gap
- 00100 - Isn't a valid gap
- 10100 - Is a valid gap
- 11111 - Isn't a valid gap
STEP 1
Get bits representation one by one from the Rigth to the Left.
That means, for n=4, I'll get first a Zero, then another Zero, then a One, finally a Zero. [0,1,0,0]
4 -> 0100
STEP 2
Start looking for the first '1' - since our flag 'hasStartPattern' is false in the first iteration, we'll look for the first occurrence of '1', that means we have a valid start pattern and we change the flag 'hasStartPattern' to true for the next iterations we should validate if the current bit is '0' and use a counter, in this case 'candidates'.
Only if, there is another '1' in the incoming bits, we are sure that we have a valid binary gap, then we compare our previous 'candidates' with our current 'gapCounter' in order to keep the highest one.
In case that there isn't another '1' to close the gap, we never change the value of 'gapCounter' and we return 0
-(int)solutionOne:(int)n {
BOOL hasStartPattern = NO;
int candidates = 0;
int gapCounter = 0;
while(n){
// STEP 1
NSString *bit = (n & 1) ? @"1": @"0";
n /= 2;
// STEP 2
if ( hasStartPattern && [bit isEqualToString:@"0"]) {
candidates++;
}
else if ( hasStartPattern && [bit isEqualToString:@"1"]) {
// At least one '1' exist as a close pattern
if (candidates > gapCounter) {
gapCounter = candidates;
}
candidates = 0;
}
else if ([bit isEqualToString:@"1"]) {
hasStartPattern = YES; // At least one '1' exist as an open pattern
}
}
return gapCounter;
}
here is my solution.
It is 100/100.
I think it can be polished though.
class Solution {
public int solution(int N) {
String s = Integer.toBinaryString(N);
int ctr = 0;
for (int x = 0; x < s.length(); x++){
if (s.substring(x,x+1).equals("1")){
ctr++;
}
}
int result[] = new int[ctr];
boolean flag = false;
int fCtr = 0;
for(int y = 0; y < s.length(); y++){
if(s.substring(y,y+1).equals("1")){
flag = true;
if(flag == true){
fCtr++;
}
}
else if (s.substring(y,y+1).equals("0") && flag == true && fCtr < ctr){
result[fCtr]++;
}
}
int ans = 0;
for (int d = 0; d < result.length; d++){
if (ans <= result[d]){
ans = result[d];
}
}
return ans;
}
}
I think this one is a very small code
public int solution(int N)
{
string binary = Convert.ToString(N, 2);
binary = binary.TrimEnd(new Char[] { '0' });
var gaps = binary.Split('1');
int max = 0;
foreach (var item in gaps)
{
if (!string.IsNullOrEmpty(item))
if(item.Length > max)
max = item.Length;
}
return max ;
}
here mine
public int solution(int N) {
String binary = Integer.toBinaryString(N);
LinkedList<Integer> gaps = new LinkedList<>();
int countGap = 0;
int j = 0;
for (int i = 1; i < binary.length() - 1; i++) {
if (binary.charAt(i) == '0') {
countGap++;
} else {
gaps.add(j, countGap);
j++;
countGap = 0;
}
}
gaps.add(j, countGap);
if (binary.charAt(binary.length() - 1) == '0') {
gaps.set(gaps.size() - 1, 0);
}
Collections.sort(gaps);
return gaps.getLast();
}
Here is my solution. (Scala)
It is 100/100.
object Solution {
def solution(n: Int): Int = {
val regex = raw"(?=(10*1))".r
val result = regex.findAllMatchIn(n.toBinaryString).map(_.group(1)) match {
case re:Iterator[String] if !re.isEmpty => (re.toList.map(Integer.parseInt(_, 2)).sorted.last.toBinaryString.length - 2)
case _ => 0
}
result
}
}
来源:https://stackoverflow.com/questions/40946025/is-my-code-solution-for-binary-gap-is-correct-or-not-what-should-i-improved-in