LeetCode-Easy-Java-Count Binary Substrings

来源:互联网 发布:鲜活的数据 pdf 下载 编辑:程序博客网 时间:2024/06/04 18:16

题目描述

Give a string s, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.

Substrings that occur multiple times are counted the number of times they occur.

Example 1:

Input: "00110011"Output: 6Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".
Notice that some of these substrings repeat and are counted the number of times they occur.
Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together.

Example 2:

Input: "10101"Output: 4Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.

Note:

  • s.length will be between 1 and 50,000.
  • s will only consist of "0" or "1" characters.

    给定一个字符串s,找到包含0和1数目相同的的子串,返回它的个数,且这些0和1在子串中必须是连续出现的。若同一子串多次出现,计算结果是它出现的总次数。
    例如 字符串“00110011”,首先会找到第一个满足条件的子串“0011”,它有2个0,2个1.然后是01,1100,10,0011,01 。
    总共找到了6个满足条件的子串。

    解决思路:这是我做的第一道字符串的题,但是解决思路似乎与数组没什么差别,两轮遍历,每一位都判断它后一位是否与他相同,若相同就继续判断下一位;若不同则计算是否对称。计算对称的方法,举例,若先检测到了3个0,就判断后面是否有3个1,用num0与num1记录子串中0或1的个数。

    代码如下:

    public int countBinarySubstrings(String s) {        int result = 0;        if(s.length()<2){            return 0;        }        char[] sArray=s.toCharArray();        for(int i=0;i<s.length()-1;i++){            int num0=0;            int num1=0;            for(int j=i+1;j<s.length();j++){                if(sArray[i]==sArray[j]){                    if(num1==0){                        num0++;                    }else {                        break;                    }                }else if(sArray[i]!=sArray[j]){                    if(num0==num1){                        result++;                        break;                    }else {                        num1++;                    }                }            }        }        return result;    }

    但是该方法超过了时间限制,确实很不高效啊,因为每一位都要遍历。因此思考改进的方法。如果前面连续出现了num0个1或0,后面又连续出现num1个0或1,那么这段子串中,具有相同子串的数目就是num0和num1中的最小值。例如,0001111,有连续3个0,连续4个1,其中具有相同0和1数目的子串有:01,0011,000111,也就是3个。因为前3个0的有效子串,我们都已经找到了,所以不需要再再判断了我们就可以直接从1开始再次计算

    改进代码如下:

    public int countBinarySubstrings(String s) {        int result = 0;        int index=0;        if(s.length()<2){            return 0;        }        char[] sArray=s.toCharArray();        for(int i=0;i<s.length()-1;i++){            int num0=0;            int num1=0;            for(int j=i;j<s.length();j++){                if(sArray[i]==sArray[j]){                    if(num1>0){                      result=result+Math.min(num0,num1);                      i=i+num0-1;                        break;                    }else{                      ++num0;                    }                }else {                    ++num1;                    if(j==s.length()-1){                        result=result+Math.min(num0,num1);                        i=s.length();                        break;                    }                }            }        }        return result;    }

    下面分析一下leetcode上的优秀代码:

        public int countBinarySubstrings(String s) {        int count=0,prev=0,cur=1;        for(int i=1;i<s.length();i++){            if(s.charAt(i-1)!=s.charAt(i)){                count+=Math.min(prev,cur);                prev = cur;                cur = 1;            }else{                cur++;            }        }                return count+ Math.min(prev,cur);    }


    这个代码思路与我们的思路一样,但是代码就完全简化的多,我因为受到第一次想法的限制,所以还是使用了两套循环,其实一次循环足以解决问题。它的关键点在于,找到前一位与后一位不同的地方,此时记录前面连续0或1的个数,取最小值。
  • 其中cur值得是当前连续的1或0的个数,prev是前面具有相同1或0的个数。例如,000111001,第一次发现前一位与后一位不同的地方是000111001,此时cur=3 prev=0,所以结果为0,赋值prev=cur=3,下一次发现前一位与后一位不同的地方是000111001,此时cur=3,prev=3,所以result=3。最后一位也是这样判断。

  • 学习算法知识点 可以 关注 FunctionY csdn博客。



    原创粉丝点击