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();

    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值