呜呜哈的博客

读读论文写写代码

leetcode题解-686. Repeated String Match && 38. Count and Say

先看686这道题目:

Given two strings A and B, find the minimum number of times A has to be repeated such that B is a substring of it. If no such solution, return -1.

For example, with A = "abcd" and B = "cdabcdab".

Return 3, because by repeating A three times (“abcdabcdabcd”), B is a substring of it; and B is not a substring of A repeated two times ("abcdabcd").

Note:
The length of A and B will be between 1 and 10000.

给了两个字符串A和B,需要我们找出A重复多少次才能包含B这个子串,最简单的思路就是不断地重复A,直到A包含了B,或者A的长度已经足够大,即便再添加也没有什么意义,这时就说明A无法包含B,直接返回-1即可。很容易想到,当A的长度大于B时也就没有了添加的必要。代码如当下所示:

    public int repeatedStringMatch(String A, String B) {
        StringBuilder res = new StringBuilder(A);
        int count = 1;
        while(res.indexOf(B) < 0){
            //不断添加A,直到res的长度大于B,这时如果res包含B,则返回添加次数,否则说明无法包含,返回-1。
            //这里使用res的长度大于A+B的长度,是因为如果一开始A就比B大的话,不进行这一步判断会出错。比如A="abababaaba",B="aabaaba"
            if(res.length() - A.length() > B.length()) return -1;
            res.append(A);
            count ++;
        }
        return count;
    }

手上面这个例子启发,其实我们可以把情况分成两种,第一种是A长度大于B,那么直接使用A或者A+A判断是否包含B即可,然后如果A长度小于B,在使用上面的方法进行拼接判断,效率有很大提升,可以击败88%的用户:

    //88%
    public int repeatedStringMatch2(String A, String B) {
        if(A.length() > B.length()){
            if(A.contains(B))
                return 1;
            else if((A+A).contains(B))
                return 2;
        }
        StringBuilder res = new StringBuilder(A);
        int count = 1;
        while(res.indexOf(B) < 0){
            if(res.length() > B.length()) return -1;
            res.append(A);
            count ++;
        }
        return count;
    }

此外,我还在discuss里面发现一种效率更高的解法,可以击败99%的用户,代码如下所示:

    //99%
    public int repeatedStringMatch1(String A, String B) {
        int count = 1;
        int i = 0;
        for (int j = 0; j < B.length(); j++) {
            if (A.charAt(i) != B.charAt(j)) {
                if (count > 1) {       // already second time: no way to make B from A
                    return -1;
                }
                j = -1;    // try to match j's starting character with next i
            }

            i++;
            if (i == A.length()) {        // one more time of A
                if (j == B.length() - 1) {
                    break;
                }
                count++;
                i = 0;
                }
        }
        return count;
    }

接下来看第二道题目:

The count-and-say sequence is the sequence of integers with the first five terms as following:

1.     1
2.     11
3.     21
4.     1211
5.     111221
1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth term of the count-and-say sequence.

Note: Each term of the sequence of integers will be represented as a string.

Example 1:

Input: 1
Output: "1"
Example 2:

Input: 4
Output: "1211"

要获得第n个字符串的读法,而读法就是有m个数字n,就读mn,这样以此类推生成字符串。所以我们只需要递推生成字符串在获得其读法,然后一次生成读取即可。代码如下所示:

    //65%
    public String countAndSay(int n) {
        StringBuilder curr=new StringBuilder("1");
        StringBuilder prev;
        int count;
        char say;
        for (int i=1;i<n;i++){
            prev=curr;
            curr=new StringBuilder();
            //分别用于统计和记录数字的个数和数字
            count=1;
            say=prev.charAt(0);

            for (int j=1,len=prev.length();j<len;j++){
                if (prev.charAt(j)!=say){
                    curr.append(count).append(say);
                    count=1;
                    say=prev.charAt(j);
                }
                else count++;
            }
            curr.append(count).append(say);
        }
        return curr.toString();

    }
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuchonge/article/details/78522866
文章标签: leetcode string
个人分类: leetcode刷题
所属专栏: Leetcode刷题总结--java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭