左旋转字符串&&字符串中第一个匹配下标&&重复子字符串(剑指58&&LeetCode 28&&459)

题目

剑指 Offer 58 - II. 左旋转字符串

思路

最开始想到的就是使用字符串的substring方法,进行重新拼接。

看了题解,也有其他思路:先翻转前n个字符、再翻转后length()-n个字符,最后再将整个字符进行翻转。

代码

public String reverseLeftWords_1(String s, int n) {
        // 先反转前n个字符,再反转后面部分的字符 最后将整个字符进行反转
        StringBuilder s_1 = revers(new StringBuilder(s), 0, n-1);
        StringBuilder s_2 = revers(s_1, n, s_1.length()-1);
        return s_2.reverse().toString();

    }
public StringBuilder revers(StringBuilder s, int a, int b){
        // 将字符s中[a,b]区间的字符进行翻转
        int strat = a;
        int end = b;
        while (end >= strat){
        // 使用一个temp来辅助翻转
            char temp = s.charAt(strat);
            s.setCharAt(strat, s.charAt(end));
            s.setCharAt(end, temp);
            end --;
            strat++;
        }
        return s;
    }
public String reverseLeftWords(String s, int n) {
        // 左旋字符串可用理解为子串的拼接
        String s_formal = s.substring(n, s.length());
        s_formal += s.substring(0,n);
        return s_formal;

    }

题目

28. 找出字符串中第一个匹配项的下标

思路

有三种思路:1)暴力;2)利用substring暴力;3)KMP

代码 

public int strStr_1(String haystack, String needle) {
        int l_2 = 0;
        if(haystack.length() < needle.length()){
            return -1;
        }
        while (l_2 <=haystack.length() - needle.length()){
            String temp = haystack.substring(l_2, l_2+needle.length());
            if(temp.equals(needle)){
                return l_2;
            }
            l_2 ++;
        }
        return -1;

    }
    public int KMP(String haystack, String needle) {
        int[] next = get_next(needle);
        int j = 0;
        for (int i = 0; i < haystack.length(); i++) {
            while (j >= 1 && haystack.charAt(i) != needle.charAt(j))
            {
                j = next[j-1];
            }
            if(haystack.charAt(i) == needle.charAt(j)){
                j ++;
            }
            if(j == needle.length()){
                return (i - needle.length() + 1);
            }
        }
        return -1;

    }
    public int[] get_next(String s){
        // 初始化
        int[] next = new int[s.length()];
        int j = 0;
        next[0] = j;
        //进入循环
        for (int i = 1; i < s.length(); i++) {
            while ( j > 0 && s.charAt(i) != s.charAt(j)){
                j = next[j-1];
            }
            if(s.charAt(i) == s.charAt(j)){
                j ++;
            }
            next[i] = j;
        }

        return next;
    }
    public int strStr(String haystack, String needle) {
        int l_1 = 0, l_2 = 0;
        while (l_2 < haystack.length()){
            while(l_1 < needle.length() &&l_2 < haystack.length() && haystack.charAt(l_2) == needle.charAt(l_1)){
                l_2 ++;
                l_1 ++;
            }
            if(l_1 >= needle.length()){
                return l_2 - l_1;
            }
            if(l_2 >= haystack.length()){
                return -1;
            }
            l_2 -= l_1 - 1; //等价于 l_2 =l_2 - l_1 + 1;
            l_1 = 0;
        }
        return -1;

    }

题目

459. 重复的子字符串 

思路

最开始想通过字符出现次数来进行判断,但该逻辑会出现问题:比如 ababba 应该返回false 而该逻辑会返回true

看了题解,力扣 

代码 

public boolean repeatedSubstringPattern(String s) {
        // 能由子串重复多次得到的字符串
        // 则通过不超过(length-1)次循环移动得到原字符串
        // 如abab 循环左移2次后就能得到abab
        // 按该逻辑进行暴力破解 会超时,则改变为通过判断S = s+s中去掉首尾字符后是否存在s
        String s_1 = s + s;
        return s_1.substring(1,s.length()-1).contains(s);
    }

你可能感兴趣的:(小菜鸡的JAVA学习,java,算法,开发语言)